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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zytjasper/article/details/87560593

 

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

则会得到正确的结果:

展开阅读全文

没有更多推荐了,返回首页