file-type

C语言中的const与volatile深度解析

PDF文件

下载需积分: 9 | 1.31MB | 更新于2024-09-13 | 121 浏览量 | 1 下载量 举报 收藏
download 立即下载
"第五课 - const和volatile分析" 在C/C++编程中,`const`和`volatile`是两个非常重要的关键字,它们用于修饰变量的属性,帮助编译器理解和处理这些变量。`const`和`volatile`常用于嵌入式系统、驱动程序开发以及多线程编程等领域。 `const`关键字的主要作用是声明一个只读变量,表示该变量的值在声明后不能被修改。在C语言中,`const`修饰的变量可以理解为一种常量,但与`#define`预处理器宏定义的常量不同,`const`变量有存储空间,可以参与类型检查,更安全。例如: ```c const int a = 5; // 声明一个只读整型变量a,初始值为5 ``` 尝试修改`const`变量的值会导致编译错误。然而,如果`const`变量是通过指针或引用间接修改,那么需要特别注意,因为在某些情况下(比如非静态内部链接的全局`const`变量)编译器可能允许这种修改,但通常这不是推荐的做法。 `volatile`关键字则用于告诉编译器,某个变量的值可能会在编译器不知情的情况下发生变化,例如由硬件中断、多线程环境中的其他线程或者其他非本地的副作用引起。这使得每次访问`volatile`变量时,编译器都不会对它进行优化,而是每次都从内存中读取最新值: ```c volatile int sensor_value; // 声明一个volatile变量,表示传感器读数 ``` 在嵌入式系统中,`volatile`常用于与硬件交互的场合,如读取传感器数据或控制硬件寄存器。在多线程环境中,`volatile`也可以用于标记共享变量,确保多线程间的同步。 当`const`和`volatile`一起使用时,它们分别修饰变量的读写属性。例如,`const volatile`表示一个变量既不能被程序修改,又可能在编译器不知情的情况下被外部因素改变。这在某些特定的硬件接口或者多线程并发访问的共享资源中可能会用到。 理解和正确使用`const`和`volatile`对于编写高效、健壮的C/C++代码至关重要。它们可以帮助避免不必要的错误,提高代码的可读性和可维护性。在实际编程中,应根据变量的实际行为来选择是否使用这两个关键字,以便让编译器更好地理解程序逻辑。

相关推荐

filetype

/*------------------------ 系统配置 ------------------------*/ #include "ti_msp_dl_config.h" // TI官方驱动库 #define ALARM_THRESHOLD 1500 // ADC报警阈值(根据实际标定调整) #define FILTER_WINDOW 7 // 中值滤波窗口大小 /*------------------------ 硬件接口定义 ------------------------*/ // FSR406连接配置 #define FSR_ADC_CHANNEL DL_ADC_INPUT_CH0 // 使用ADC通道0 #define BUZZER_PIN DL_GPIO_PIN_13 // 蜂鸣器控制引脚(PB13) /*------------------------ 全局变量 ------------------------*/ volatile uint16_t g_adc_raw_value = 0; // ADC原始值 volatile bool g_adc_conversion_done = false;// ADC转换完成标志 /*------------------------ ADC初始化 ------------------------*/ void ADC_Init_FSR406(void) { // ADC时钟配置 DL_ADC_setClockConfig(ADC_0_INST, DL_ADC_CLOCK_SYSCLK, DL_ADC_CLOCK_DIVIDER_1, DL_ADC_CLOCK_DIVIDER_1); // ADC参数配置(单次转换模式) DL_ADC_init(ADC_0_INST); DL_ADC_enableConversions(ADC_0_INST); DL_ADC_setResolution(ADC_0_INST, DL_ADC_RESOLUTION_12BIT); DL_ADC_setReferenceVoltage(ADC_0_INST, DL_ADC_REFERENCE_VOLTAGE_VREF); DL_ADC_enableChannel(ADC_0_INST, FSR_ADC_CHANNEL); // 配置ADC中断 DL_ADC_enableConversionCompleteInterrupt(ADC_0_INST); NVIC_EnableIRQ(ADC_0_INST_INT_IRQn); } /*------------------------ 中值滤波函数 ------------------------*/ uint16_t Median_Filter(uint16_t *buffer) { uint16_t temp[FILTER_WINDOW]; memcpy(temp, buffer, sizeof(uint16_t)*FILTER_WINDOW); // 冒泡排序 for(int i=0; i<FILTER_WINDOW-1; i++) { for(int j=0; j<FILTER_WINDOW-i-1; j++) { if(temp[j] > temp[j+1]) { uint16_t swap = temp[j]; temp[j] = temp[j+1]; temp[j+1] = swap; } } } return temp[FILTER_WINDOW/2]; // 返回中值 } /*------------------------ ADC中断处理 ------------------------*/ void ADC_0_INST_IRQHandler(void) { if(DL_ADC_getStatus(ADC_0_INST) & DL_ADC_STATUS_CONVERSION_COMPLETE) { g_adc_raw_value = DL_ADC_getData(ADC_0_INST); g_adc_conversion_done = true; DL_ADC_clearStatus(ADC_0_INST, DL_ADC_STATUS_CONVERSION_COMPLETE); } } /*------------------------ 报警控制 ------------------------*/ void Trigger_Alarm(bool enable) { static uint8_t alarm_counter = 0; const uint8_t DEBOUNCE_COUNT = 3; if(enable) { if(++alarm_counter >= DEBOUNCE_COUNT) { DL_GPIO_setPins(GPIOB_PORT, BUZZER_PIN); // 开启蜂鸣器 } } else { alarm_counter = 0; DL_GPIO_clearPins(GPIOB_PORT, BUZZER_PIN); // 关闭蜂鸣器 } } /*------------------------ 主函数 ------------------------*/ int main(void) { // 系统时钟初始化(32MHz) DL_SystemInit_SYSCTL_32MHZ_INTERNAL(); // GPIO初始化 DL_GPIO_initDigitalOutput(GPIOB_PORT, BUZZER_PIN); // ADC初始化 ADC_Init_FSR406(); // 主循环 while(1) { if(g_adc_conversion_done) { static uint16_t adc_buffer[FILTER_WINDOW]; static uint8_t buf_index = 0; // 更新滤波缓冲区 adc_buffer[buf_index++] = g_adc_raw_value; if(buf_index >= FILTER_WINDOW) buf_index = 0; // 获取滤波后数值 uint16_t filtered_val = Median_Filter(adc_buffer); // 压力异常判断 Trigger_Alarm(filtered_val > ALARM_THRESHOLD); // 触发下一次转换 DL_ADC_startConversion(ADC_0_INST); g_adc_conversion_done = false; } __WFI(); // 进入低功耗模式 } }为什么其中的DL_ADC_会报错

filetype

#include <hidef.h> #include "derivative.h" // ---------------------- // 数码管驱动定义 // ---------------------- #define LEDData PTAD #define LEDData_D PTADD #define LEDCs PTBD #define LEDCs_D PTBDD const unsigned char LED_Table[17] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x80,0x77,0x7C,0x39,0x5E,0x79,0x71}; unsigned char Display_Buf[4] = {0, 0, 0, 0}; unsigned char Current_Pos = 0; // ---------------------- // ADC 模块定义(PTB7) // ---------------------- #define ADC_CHANNEL PTB7 #define ADCH_CHANNEL 7 // PTB7 对应 ADC 通道7 //#define APCTL1 (*(volatile unsigned char *)0x002C) // 端口控制寄存器1 //#define ADC1CFG (*(volatile unsigned char *)0x0170) // ADC 配置寄存器 //#define ADC1SC2 (*(volatile unsigned char *)0x0172) // ADC 状态控制寄存器2 //#define ADC1SC1 (*(volatile unsigned char *)0x0171) // ADC 状态控制寄存器1 #define ADSR (*(volatile unsigned char *)0x0034) // ADC 状态寄存器(AW60地址可能为0x0034) #define COCO 7 // 转换完成标志位 // ---------------------- // 函数声明 // ---------------------- void delay(int count); void LED_ScanDisplay(); unsigned int Get_ADC_Value(); void main(void) { EnableInterrupts; PTADD = 0xFF; // A口输出 PTBDD = 0xFF; // B口输出 // 初始化 ADC 为 PTB7 输入 APCTL1 &= ~(1 << 7); // PTB7 设为模拟输入(清除第7位) ADC1CFG = 0x70; // 10位模式,长采样时间,总线时钟/16(0x70=0b01110000) ADC1SC2 = 0x00; // 软件触发,禁止比较功能 ADC1SC1 = ADCH_CHANNEL; // 选择通道7 while (1) { __RESET_WATCHDOG(); unsigned int adc_value = Get_ADC_Value(); // 获取 ADC 值(0-1023) float voltage = (adc_value * 5.0) / 1024.0; // 转换为电压 // 拆分显示数据 unsigned char d1 = (unsigned char)voltage; unsigned char d2 = (unsigned char)((voltage * 10) % 10); unsigned char d3 = (unsigned char)((voltage * 100) % 10); Display_Buf[0] = d1; Display_Buf[1] = d2 + 10; // 小数点 Display_Buf[2] = d3; Display_Buf[3] = 0; LED_ScanDisplay(); } } // ---------------------- // 数码管扫描函数(不变) // ---------------------- void LED_ScanDisplay() { LEDData = 0x00; LEDCs = 0xFF; switch (Current_Pos) { case 0: LEDCs = 0xFE; break; case 1: LEDCs = 0xFD; break; case 2: LEDCs = 0xFB; break; case 3: LEDCs = 0xF7; break; } LEDData = LED_Table[Display_Buf[Current_Pos]]; Current_Pos = (Current_Pos + 1) % 4; delay(2); } // ---------------------- // ADC 数据获取函数(修正) // ---------------------- unsigned int Get_ADC_Value() { ADC1SC1 = ADCH_CHANNEL; // 触发转换 while (!(ADSR & (1 << COCO))); // 等待完成 // AW60 ADC 结果存储在 ADC1R(16位),高10位有效(右对齐) return (ADC1R >> 6) & 0x03FF; // 提取10位数据(0-1023) } // ---------------------- // 延时函数(不变) // ---------------------- void delay(int count) { int i, j; for (; i < count; i++) for (j = 0; j < 1000; j++); } 修改代码出现的问题