前言
笔记是人类的第二大脑,以前的我也总是在记录上所懈怠,遇到不会的就csdn cv 一顿操作,始终不得其内涵。从这个赛事开始,我来学习大佬在嵌入式上的理解,自己做好每次记录,辅助记忆的同时也能亲手过一次知识与项目。希望能在赛事上大放光彩
一、ADC/DAC是什么?
A指模拟信号 D指数字信号 C指转化
ADC:模数转换器,将模拟信号转化为数字信号;具体使用有:温度传感器,压力传感器等。
DAC:数模转换器,将数字信号转化为模拟信号;具体使用有:音频设备,马达控制器等。
二、常用函数
1.ADC模数常用函数
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)
举例:HAL_ADC_Start(&hadc1);
函数描述:启动名为 hadc1 的ADC,初始化ADC并开始模数转换。
hadc1 是指向ADC的指针
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
举例:HAL_ADC_PollForConversion(&hadc1, 10);
函数描述:一个轮询函数,用来检查ADC转换是否完成。它检查ADC的EOC(End of Conversion)标志,以确定转换是否完成。参数 10 表示超时时间,单位为毫秒。如果在10毫秒内转换没有完成,这个函数将返回一个超时错误。
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc)
举例:adc = HAL_ADC_GetValue(&hadc1);
函数描述:从 hadc1指向的ADC获取转换结果,并将其存储在变量 adc 中。HAL_ADC_GetValue 函数读取ADC的数据寄存器,并返回转换后的数字值。
2.DAC数模常用函数
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel)
举例:HAL_DAC_Start(&hdac1, DAC_CHANNEL_2);
函数描述:HAL_DAC_Start 函数激活 DAC准备输出模拟信号。
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel,
uint32_t Alignment, uint32_t Data)
举例:HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_R,temp);
函数描述:HAL_DAC_SetValue 函数用于配置 DAC 输出的具体电压值
&hdac1:指向 DAC 实例的指针。 DAC_CHANNEL_2:指定操作的是哪个 DAC 通道 DAC_ALIGN_12B_R:指定数据对齐式,这里是 12 位右对齐。 temp:决定输出信号的具体电压,DAC 会将这个数字值转换为相应的 模拟电压值!
三、模拟输出原理图
PB15——AD1
PB12——AD2
四、使用流程
adc篇
配置cubemx
以PB12与PB15为例
将PB12配置为ADC1_IN11,将PB15配置为ADC2_IN15
将ADC1中的通道11和ADC2中的通道15都配置为Single-ended
创建文本文件,写代码,再强行改后缀名改变文件类型,以第一篇中模块化的步骤移植进程序。
文件名不能为adc.c/adc.h,因为库中有这个名字的文件。所以建议改成 badc.c/badc.h。
badc.c代码
#include "main.h"
#include "adc.h"
#include "badc.h"
uint16_t getADC1(void)
{
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
uint16_t adc = 0;
HAL_ADC_Start(&hadc1);
adc = HAL_ADC_GetValue(&hadc1);
return adc;
}
uint16_t getADC2(void)
{
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
uint16_t adc = 0;
HAL_ADC_Start(&hadc2);
adc = HAL_ADC_GetValue(&hadc2);
return adc;
}
void getManyADC1(double*data,int n)
{
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
int i=0;
for(i=0;i<n;i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion (&hadc1,50);
data[i] = ((double)HAL_ADC_GetValue(&hadc1)/4096)*3.3;
}
HAL_ADC_Stop(&hadc1);
}
void getManyADC2(double*data,int n)
{
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
int i=0;
for(i=0;i<n;i++)
{
HAL_ADC_Start(&hadc2);
HAL_ADC_PollForConversion (&hadc2,50);
data[i] = ((double)HAL_ADC_GetValue(&hadc2)/4096)*3.3;
}
HAL_ADC_Stop(&hadc2);
}
badc.h代码
#ifndef __BADC_H
#define __BADC_H
#include "main.h"
/*单adc单通道*/
uint16_t getADC1(void);//hadc1
uint16_t getADC2(void);//hadc2
/**************/
/*单adc多通道*/
void getManyADC1(double*data,int n);
void getManyADC2(double*data,int n);
/**************/
#endif
至此,已经做好了adc单通道和多通道的库了。接下来进入实际操作阶段。
adc实验代码
实验:使用电压采集1旋钮和电压采集2旋钮分别控制输出数字电压,并转换为模拟电压值显示在屏幕上。
即:模拟电压通过ADC变成数字电压,数字电压通过公式计算变成模拟电压显示到屏幕上。
单通道单输入实验
1.调用库
lcd_print_float(White,Red,8,getADC1()*3.3/4096);
lcd_print_float(White,Red,9,getADC2()*3.3/4096);
2.修改一下lcd的库方便显示
void page1(void)
{
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
LCD_DisplayStringLine(Line0, (uint8_t *)" ");
LCD_DisplayStringLine(Line1, (uint8_t *)" ");
LCD_DisplayStringLine(Line2, (uint8_t *)" ");
LCD_DisplayStringLine(Line3, (uint8_t *)" ");
LCD_DisplayStringLine(Line4, (uint8_t *)" TEST ");
LCD_SetBackColor(White);
LCD_SetTextColor(Blue);
LCD_DisplayStringLine(Line5, (uint8_t *)" ON ");
LCD_DisplayStringLine(Line6, (uint8_t *)" ");
LCD_DisplayStringLine(Line7, (uint8_t *)" ");
LCD_DisplayStringLine(Line8, (uint8_t *)" ");
LCD_DisplayStringLine(Line9, (uint8_t *)" ");
}
void page2(void)
{
LCD_Clear(Blue);
LCD_SetBackColor(Red);
LCD_SetTextColor(White);
LCD_DisplayStringLine(Line0, (uint8_t *)" ");
LCD_DisplayStringLine(Line1, (uint8_t *)" ");
LCD_DisplayStringLine(Line2, (uint8_t *)" ");
LCD_DisplayStringLine(Line3, (uint8_t *)" ");
LCD_DisplayStringLine(Line4, (uint8_t *)" TEST ");
LCD_SetBackColor(Red);
LCD_SetTextColor(Blue);
LCD_DisplayStringLine(Line5, (uint8_t *)" OFF ");
LCD_DisplayStringLine(Line6, (uint8_t *)" ");
LCD_DisplayStringLine(Line7, (uint8_t *)" ");
LCD_DisplayStringLine(Line8, (uint8_t *)" ");
LCD_DisplayStringLine(Line9, (uint8_t *)" ");
}
void lcd_print_int(int backcolor,int textcolor,int Variable)
{
LCD_SetBackColor(backcolor);
LCD_SetTextColor(textcolor);
char text[30];
sprintf(text,"NUMBER:%d ",Variable);
LCD_DisplayStringLine(Line9, (uint8_t *)text);
}
void lcd_print_float(int backcolor,int textcolor,int line,float Variable)
{
LCD_SetBackColor(backcolor);
LCD_SetTextColor(textcolor);
char text[30];
sprintf(text,"NUMBER:%.2f ",Variable);
switch(line)
{
case 0:LCD_DisplayStringLine(Line0, (uint8_t *)text);
break;
case 1:LCD_DisplayStringLine(Line1, (uint8_t *)text);
break;
case 2:LCD_DisplayStringLine(Line2, (uint8_t *)text);
break;
case 3:LCD_DisplayStringLine(Line3, (uint8_t *)text);
break;
case 4:LCD_DisplayStringLine(Line4, (uint8_t *)text);
break;
case 5:LCD_DisplayStringLine(Line5, (uint8_t *)text);
break;
case 6:LCD_DisplayStringLine(Line6, (uint8_t *)text);
break;
case 7:LCD_DisplayStringLine(Line7, (uint8_t *)text);
break;
case 8:LCD_DisplayStringLine(Line8, (uint8_t *)text);
break;
case 9:LCD_DisplayStringLine(Line9, (uint8_t *)text);
break;
}
}
/*----- myself -----*/
void page1(void);
void page2(void);
void lcd_print_int(int backcolor,int textcolor,int Variable);
void lcd_print_float(int backcolor,int textcolor,int line,float Variable);
#endif /* __LCD_H */
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
dac篇
配置cubemx
dac实验代码
// DAC1电压设置函数
void DAC1_Set_Vol(float vol)
{
int temp;
temp = (4096 * vol/3.3f);
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_2,DAC_ALIGN_12B_R,temp);
}
DAC1_Set_Vol(2.4);
adc结合dac篇
tips:一个adc开一个通道,不能开两个,否则dac检测不了。
如dac代码所示,将PA5与PA7用杜邦线连接即可
总结
adc的单通道检测很容易忽略,如果设置了多通道时候记得注意轮询。