[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出
- 使用标准库实现本次功能的源代码已上传:
- https://github.com/yzmj0986/STM32_Std.lib_ADC_Voltage.git
MCU:STM32F103ZET6
IDE: MDK-ARM V5 +STM32CubeMX5.0.0
串口调试助手:SSCOM3.2
功能描述:通过ADC1通道1采样外部电压值,将采样的AD值和转换后的电压值通过串口打印出来。需要配置的有USART1和ADC。
一. 在 Pinout&Configuration---System Core中:
- 1. 首先设置时钟RCC的HSE(外部高速时钟)为晶振模式:Crystal/ceramic Resonator
- 2. 设置系统SYS的Debug为Serial Wire:
二. 在 Pinout&Configuration---Analog和Connectivity中:
- 1. 设置PA1为ADC1_IN1模式:
根据原理图可知ADC1的通道1的引脚为PA1,因此设置PA1为ADC1_IN1模式。
- 2. 在Configuration的Parameter Settings中设置ADC1的参数:
分别设置模式,单单个扫描和单次扫描,并在规则通道参数设置中设置为软件触发的方式。(对应的标准库代码在右上角)。
- 3. 打开USART1,并设置模式为异步收发模式Asynchronous:
- 4. 设置USART1的参数,通用的“96-N-8-1”模式,即波特率9600,N校验位(无校验),数据位数为8,停止位为1位:
三.在 Clock Configuration中:
配置时钟为72 Mhz。
四.在 Project Manager---Project中:
- 1.设置项目的名称以及保存的位置,选择Toolchain/IDE为MDK-ARM V5,
Tips:最好把Linker Settings中的Minimum Heap Size设置为0x600。
- 2.在Code Generator选项中如下勾选:
最后点Generate Code生成代码,并选择“Open Project”:
五.代码分析与改写:
和笔记4相同,同样需要用到串口输出的功能,首先将printf()函数的输出功能映射到串口上:
- 1. 首先在main.c中进行宏定义:
/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
- 2. 对于MDK-ARM编译器,在main.c中加入重定向函数:(此处与官方例程中不同,将&UartHandle改为&huart1)
/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 0 */
3. 在main.c中设置变量用于存储AD和电压值:(注意VOL_Value一定是浮点型的)
/* USER CODE BEGIN 1 */
uint16_t ADC_Value;
float VOL_Value;
/* USER CODE END 1 */
4.在while(1)循环中添加AD与电压转换程序:
步骤依次为:
① HAL_ADCEx_Calibration_Start()//校准ADC
② HAL_ADC_Start()//开启ADC
③ HAL_ADC_PollForConversion()//等待转换过程
④若if循环判断转换完成后,HAL_ADC_GetState()获取AD值存在ADC_Value中并打印。
⑤将AD值转换为电压值存在VOL_Value中并打印。
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADCEx_Calibration_Start(&hadc1); //校准
HAL_ADC_Start(&hadc1); //开启
HAL_ADC_PollForConversion(&hadc1,50); //等待转换完成
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_Value=HAL_ADC_GetState(&hadc1);
printf("检测AD值为:%d\r\n",ADC_Value);
VOL_Value=ADC_Value*3.3/4096;
printf("检测电压值为:%.2fV \r\n",VOL_Value);
}
HAL_Delay(200);
/* USER CODE END WHILE */
至此应该是完成了HAL库下ADC转换读取电压的程序,但是不知是硬件出了问题还是软件有逻辑错误,我的电压值一直很小,变化也不大,希望有遇到相同问题的朋友可以交流一下。(基于标准库函数的程序也遇到了这个问题)。
2019/2/20 10:23 更新:
针对上述问题,经过反复检查程序找到了问题。源程序如下:
u16 Get_ADC_Value(u8 ch,u8 times) //获取AD转换值的结果
{
u8 t;
u8 temp_val=0;
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); //最大的转换周期,239.5个
for (t=0;t<times;t++)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); //转换完成后退出
temp_val+=ADC_GetConversionValue(ADC1);
delay_ms(5);
}
return temp_val/times;
temp_val的取值范围是0-4095,因此应定义为32位的变量:u8 temp_val=0→u32 temp_val=0;
针对HAL库中程序,一定要定义VOL_Value为浮点型的。
则会得到正确的结果:
上一篇: 获取字符串,数组,对象长度? (js)