欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

程序员文章站 2024-02-25 15:55:39
...

 

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

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

  • 2. 设置系统SYS的Debug为Serial Wire:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

二. 在 Pinout&Configuration---Analog和Connectivity中:

  • 1. 设置PA1为ADC1_IN1模式:

根据原理图可知ADC1的通道1的引脚为PA1,因此设置PA1为ADC1_IN1模式。

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出        [STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

  • 2. 在Configuration的Parameter Settings中设置ADC1的参数:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

分别设置模式,单单个扫描和单次扫描,并在规则通道参数设置中设置为软件触发的方式。(对应的标准库代码在右上角)。

  • 3. 打开USART1,并设置模式为异步收发模式Asynchronous:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

  • 4. 设置USART1的参数,通用的“96-N-8-1”模式,即波特率9600,N校验位(无校验),数据位数为8,停止位为1位:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

三.在 Clock Configuration中:

配置时钟为72 Mhz。

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

四.在 Project Manager---Project中:

  • 1.设置项目的名称以及保存的位置,选择Toolchain/IDE为MDK-ARM V5,

Tips:最好把Linker Settings中的Minimum Heap Size设置为0x600。

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

  • 2.在Code Generator选项中如下勾选:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出

最后点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为浮点型的。

则会得到正确的结果:

[STM32CubeMX]学习笔记5:ADC模数转换电压至串口输出