c语言day8
通过过指针来访问寄存器
#define GPIO_CTLO ((uint32_t *)0x40012000)
GPIO_CTLO = 0XFFFFFFFF;
指针变量的运算
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;