嵌入式学习-Day8

c语言day8

通过过指针来访问寄存器

#define  GPIO_CTLO              ((uint32_t *)0x40012000)

GPIO_CTLO = 0XFFFFFFFF;

  • 0x40012000是一个十六进制数值,此时编译器不认为他是一个地址
  • 通过强制转换,让编译器认为他是一个地址,(uint32_t *)0x40012000此时可以将0x40012000理解为定义指针变量时,uint32_t*p中的p
  • *((uint32_t *)0x40012000)第一个*和*p=1一样,表示要访问这个地址,接下来就可以对他赋值

指针变量的运算

    uint8_t a = 0xF0;//a的地址为0x2000408
    uint8_t *p;

   p = &a;//0x2000408

     p++//指针变量+1,并不是地址值+1,而是按照定义数据类型占的字节+

p = 0x20000409

示例:将下面的数值转换为日期

//	日期,指针运算
	uint32_t date = 0x14130614;  // 32位整数,十六进制表示
	uint8_t *temp;               // 声明一个指向 uint8_t 的指针
	temp = (uint8_t*)&date;      // 将 date 的地址强制转换为 uint8_t* 类型,赋值给 temp
	uint8_t day = *temp;         // 读取 temp 指向的地址的值(即 date 的最低字节)
	temp++;
	uint8_t month = *temp;

&:取地址操作符;获取变量的地址内存

带*:当需要访问指针指向的内存中的值

指针与结构体

结构体指针变量—>成员名 ==(*结构体指针变量).成员名

用指针结构体完成三个传感器以及co2,pm2.5

在tem.c中写出指针函数

int8_t GetTempHumi(TempHumiSensor *tempHumiptr)//用来获取传感器的数据-结构体指针
{
	tempHumiptr ->id = GetCelTem(tempHumiptr ->id);
	tempHumiptr ->temp = GetCelTem(tempHumiptr ->temp);
	tempHumiptr ->humi = GetCelTem(tempHumiptr ->humi);

	return 0;
}

在main函数

//检测co2,pm、2.5,temp,humi,ID
    AirQuality airQuality;
	airQuality.temphumisensor[0].id = 0x1234;
	airQuality.temphumisensor[1].id = 0x2345;
	airQuality.temphumisensor[2].id = 0x3456;
	
	SetTemCof(GetTemCofHmi());//外部校准
	for(uint8_t i = 0; i < 3; i++)
{
	 GetTempHumi(&airQuality.temphumisensor[i]);
	
}	
	airQuality.Co2Level = GetCo2Level();
	airQuality.PM25Level = GetPm25Level();

    DisplayAirQuality(&airQuality);

在main函数中涉及到了指针与数组

数组名称除了可以代表整个数组以外sizeof(buffer),还可以保存数组的首地址

buffer == &buffer[0];

这个用途再通过指针来访问数组,以及向函数传递数组的场景

int32_t *p = buffer;

void Sort(int32_t buffer[ ])
数组名称buffer保存了数组的首地址,可以向指针变量一样,直接读取地址,不像结构体等其它类型的变量,需使用&

数组名称和指针变量的区别

  • 数组名称保存数组首地址且不需要像指针变量那样需要初始化赋值,保存的地址数组不能被改变---数组名是常量
  • 指针需要初始化地址并且可以指向任意一个地址(初始化后)
	int8_t buffer[5] = {3,2,1,5,4};
	int8_t *ptr = buffer;
	for(uint8_t i =0; i < 5; i++)
	{
		printf("*(ptr + %d) = %d\n",i, *(ptr +i));
		//配合*来访问数组元素
	}
	//或者下面这个
	for(uint8_t i =0; i < 5; i++)
	{
		printf("*(ptr + %d) = %d\n",i, ptr[i]);
		//使用指针变量的名字来访问数组的元素
	}

数组作为函数参数

示例:数组指针来互换值 

//互换整数
void Exch(int32_t nums[], int32_t res[], int32_t  n)
{//在这里nums当作指针,函数接受一个指针
	for (uint32_t i = 0; i < n; i++)
	{
		res[2*i] = nums[i];
		res[2*i+1] = nums[i+n];

	}
}	
//互换整数  mian函数
	int32_t nums[] = {1,2,3,4,4,3,2,1}, n = 4;//数组8个int32个数据类型 
	int32_t res[2*n];
	Exch(nums,res,n);

回到空气检测中,将打印函数定义为数组指针

void DisplayTemHumi(TempHumiSensor temphumisensor[],uint32_t len)
{
	for(uint8_t i = 0; i < len; i++)
	{
	printf("%d, %.1f, %d\n",temphumisensor[i].id, temphumisensor[i].temp, temphumisensor[i].humi);
	}
}
void DisplayAirQuality(AirQuality airQuality[])
{
	DisplayTemHumi(airQuality->temphumisensor,3);
	DisplayCo2Level(airQuality->Co2Level);//打印
	DisplayPm25Level(airQuality->PM25Level);//打印

}

还有在tem.c文件中曾对温度传感器求值5次求和转换为数组指针

static float CalRawAvg(float data[],uint32_t len)
{
	float res = 0;
	for(uint8_t i = 0; i < 5; i++)
	{
	res += data[i];
	}
	return res /= len;
}
float GetCelTem(uint32_t sensorID)
{
	float raw[5];
	for(uint8_t i = 0; i < 5; i++)
	{
	raw[i] = GetRawData(sensorID);
	}
	float cel = CalRawAvg(raw,5);//获取温度值

练习题目

/* 任务:
   1. 创建一个指向dev的指针
   2. 使用指针修改设备ID为0x5678
   3. 使用指针读取并打印温度值
   4. 计算并打印结构体的总大小(字节数)
*/
    typedef struct {
    uint16_t id;        // 设备ID
    uint8_t status;     // 状态标志
    uint8_t temperature; // 温度 (°C)
    uint16_t voltage;   // 电压 (mV)
} Device;

	Device dev = {0x1234, 0x01, 25, 3300};
	Device *devzhizhen = &dev;
	devzhizhen ->id = 0x5678;
	printf("dev temp %d\n",devzhizhen ->temperature);

练习2

/* 任务:
   1. 使用指针运算,计算数组所有元素的和
   2. 打印每个元素的地址和值
   3. 找出数组中的最大值
*/
	int arr[5] = {10, 20, 30, 40, 50};
    int *p = arr;
    int sum = 0;
    int max = *p;  // 初始化为第一个元素
    
    // 一次遍历,同时计算总和和最大值
    for(int i = 0; i < 5; i++)
 {
        // 打印地址和值
        printf("地址: %p, 值: %d\n", (void*)p, *p);  
        // 累加总和
        sum += *p;    
        // 更新最大值
        if(*p > max) 
       {
            max = *p;
        } 
        p++;  // 指针后移
    }
    printf("总和: %d\n", sum);
    printf("最大值: %d\n", max);

练习3

	/* 任务:
   1. 创建一个SensorData结构体变量data
   2. 使用指针初始化data的所有成员:
      - 温度: 25.5°C (即255)
      - 湿度: 60.2% (即602)
      - 气压: 1013.2hPa (即10132)
      - 状态: 所有标志位设为1 (正常)
   3. 使用指针修改温度为26.0°C
   4. 使用位操作将通信状态(comm_ok)设为0 (异常)
   5. 验证并打印所有数据,包括状态寄存器的二进制表示
*/
	// 传感器状态寄存器定义
typedef struct {
    uint8_t voltage_ok : 1;   // 位0: 电压正常 (1=正常)
    uint8_t temp_ok : 1;      // 位1: 温度正常 (1=正常)
    uint8_t comm_ok : 1;      // 位2: 通信正常 (1=正常)
    uint8_t reserved : 5;     // 位3-7: 保留位
} SensorStatus;

// 传感器数据结构体
typedef struct {
    uint16_t temperature;     // 温度值 (0.1°C)
    uint16_t humidity;        // 湿度值 (0.1%)
    uint16_t pressure;        // 气压值 (0.1hPa)
    SensorStatus status;      // 状态寄存器
} SensorData;
	SensorData data ={0};
	SensorData *sensorData = &data;
	sensorData ->temperature = 255;
	sensorData ->humidity = 602;
	sensorData ->pressure = 10132;
	sensorData->status.voltage_ok = 1;

	sensorData ->temperature = 260;
	
// 初始化状态寄存器(所有标志位设为1)
    sensorData->status.voltage_ok = 1;
    sensorData->status.temp_ok = 1;
    sensorData->status.comm_ok = 1;
	
	 sensorData->status.comm_ok = 0;
	 // 方法2:使用位操作(假设status是uint8_t类型)
    // uint8_t *status_byte = (uint8_t*)&sensorData->status;
    // *status_byte &= ~(1 << 2);  // 清除位2

练习4拓展:

/* 任务:
   1. 创建一个SensorData结构体变量data
   2. 使用指针初始化data的所有成员:
      - 温度: 25.5°C (即255)
      - 湿度: 60.2% (即602)
      - 气压: 1013.2hPa (即10132)
      - 状态: 所有标志位设为1 (正常)
   3. 使用指针修改温度为26.0°C
   4. 使用位操作将通信状态(comm_ok)设为0 (异常)
   5. 验证并打印所有数据,包括状态寄存器的二进制表示
*/
// 传感器状态寄存器定义
typedef struct {
    uint8_t voltage_ok : 1;   // 位0: 电压正常 (1=正常)
    uint8_t temp_ok : 1;      // 位1: 温度正常 (1=正常)
    uint8_t comm_ok : 1;      // 位2: 通信正常 (1=正常)
    uint8_t reserved : 5;     // 位3-7: 保留位
} SensorStatus;

// 传感器数据结构体
typedef struct {
    uint16_t temperature;     // 温度值 (0.1°C)
    uint16_t humidity;        // 湿度值 (0.1%)
    uint16_t pressure;        // 气压值 (0.1hPa)
    SensorStatus status;      // 状态寄存器
} SensorData;

 

你可能感兴趣的:(学习)