adc 接收cube_STM32CubeMX学习笔记5:ADC模数转换电压至串口输出

本文介绍了使用STM32F103ZET6通过STM32CubeMX配置ADC1通道1进行电压采样,并通过USART1串口输出AD值和转换后的电压值。配置步骤包括设置时钟、ADC与USART参数,以及代码修改,涉及ADC校准、转换启动、数据获取和电压计算。最后解决了电压值显示不准确的问题。
摘要由CSDN通过智能技术生成

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

22a94bb0db6fb70d726551a6fd5288a5.png

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

99f500fcc8f85ca6c66887f25a8156ef.png

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

1. 设置PA1为ADC1_IN1模式:

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

6ec6321e4130c2f4cacdfc0a94ee28b2.png

2bf0d2fc01609e8394992740cec042c3.png

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

9dfd2c116f3aab5d24821ca40bc5e4b5.png

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

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

6a0c0475ec9292d3d8e805364fb4cbe0.png

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

0d65e39e45d85d40fb15322ac9a9b121.png

三.在 Clock Configuration中:

配置时钟为72 Mhz。

9b29e378bc6e12b13315c56c8c04eea0.png

四.在 Project Manager---Project中:

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

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

ad18fc46318e4817e4be5a0cb24cbfd7.png

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

04fa1d4a578461ca52a7611efc8197cb.png

最后点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值为:%drn",ADC_Value);

VOL_Value=ADC_Value*3.3/4096;

printf("检测电压值为:%.2fV rn",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{

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

则会得到正确的结果:

6a061c740386ce92181711dd99633501.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值