因为需要获取角度和电流这两个量,所以需要使用ADC。
什么是ADC? ADC(Analog-to-digital converter模拟数字转换器)用于将连续变化的量转换成离散的整数量更利于单片机处理。
可以谈一下ADC大致的实现过程:也就是每间隔很短的时间采集一次外部的值并与基准值进行比较,比较的结果按照分辨率来产生一个离散的值作为结果。这个时间间隔叫采样周期。采样周期也不是随便选择的,而是根据外部连续量的性质进行选择,这里面涉及到奈奎斯特定理。
STM8 单片机因为价格低廉功能全面封装体积小而应用广泛。所以最近在项目中使用的正是这种单片机具体型号是:STM8S103F3P. 这款单片机有8K代码容量,1K内存,内部集成640Byte容量的存储芯片。此款芯片ADC分辨率是10位。
我要做的是采集电位器的电压值和电流传感器的电流值。电位器在不通过的旋转角度上分得的电压不同。使用两个通道分别采集电压和电流。下面直接贴程序,如果有不理解的地方后面会有说明。
1.初始化ADC
1 void ADC_Res_Init(void) 2 { 3 ADC_CR1= 0x02; //这里设置分频系数为2 连续转换模式 先禁止ADC转换 4 ADC_CR2=0x08; //设置数据右对齐 禁止扫描模式 5 ADC_CSR = 0x04; //设置转换通道为AIN4 6 ADC_TDRL = 0x10; //禁止AIN4施密特触发器 7 ADC_CR1 |= 0x01; //第一次写1是从低功耗模式唤醒 8 ADC_CR1 |=0x01; //再次写1启动ADC转换 9 } 10 void ADC_Ele_Init(void) 11 { 12 ADC_CR1= 0x02; //这里设置分频系数为2 连续转换模式 先禁止ADC转换 13 ADC_CR2=0x08; //设置数据右对齐 禁止扫描模式 14 ADC_CSR = 0x02; //设置转换通道为AIN2 15 ADC_TDRL = 0x10; //禁止AIN4施密特触发器 16 ADC_CR1 |= 0x01; //第一次写1从低功耗模式唤醒 17 ADC_CR1 |=0x01; //再次写1启动ADC转换 18 }
2.获取结果
uint16_t ADC_GetConversionValue(void) { uint16_t value,temph; uint8_t templ;//定义templ存储低8位数据 temph存储高8位数据 while(!(ADC_CSR & 0x80));//等待转换完成 templ = ADC_DRL; temph = ADC_DRH;//读取ADC转换在左对齐和右对齐模式下 读取数据的顺序不同 参考STM8寄存器.PDFP371 value = (unsigned int)(templ | (temph << 8));//注意是10位的转换精度 value、temph应为unsigned int 变量 return value; }
3.平均值滤波
u16 Adc_Average(u8 times) { u32 sum = 0; u8 count; for (count=0;count<times;count++) { sum =sum + ADC_GetConversionValue(); } return (u16)(sum/times); }
上面的程序主要涉及到ADC_CR1,ADC_CR2,ADC_CSR,ADC_TDRL,ADC_DRL,ADC_DRH这几个寄存器。
1>ADC_CR1:ADC配置寄存器1
2>ADC_CR1:ADC配置寄存器2
3>ADC_CSR控制/状态寄存器
4>施密特触发器禁止寄存器ADC_TDRL
5>数据寄存器ADC_DRH,ADC_DRL