目录

银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-04-13 gingko 初次建立

STM32CubeMX教程十——ADC实验

1. 新建工程:在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR  2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32F407IGTx。  3. 配置RCC,使用外部时钟源  4. 配置调试引脚  5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output  6. 引脚模式配置  7. 配置ADC引脚   8. 配置UART  9. 时钟源设置,选择外部高速时钟源,配置为最大主频  10. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK5  11. 点击Code Generator,进行进一步配置

自行选择方式即可

12. 然后点击GENERATE CODE 创建工程  创建成功,打开工程。





实验十:ADC实验——电源监控

一、 实验目的与意义

  1. 了解STM32 ADC结构。
  2. 了解STM32 ADC特征。
  3. 掌握ADC的使用方法。
  4. 掌握STM32 HAL库中ADC属性的配置方法。
  5. 掌握KEIL MDK 集成开发环境使用方法。

二、 实验设备及平台

  1. iCore3 双核心板。点击购买
  2. JLINK(或相同功能)仿真器。点击购买
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、ADC简介

2、ADC分为以下几种类型:

  1. 积分型:积分型AD工作原理是将输入电压转换成时间(脉冲宽度信号)或频率(脉冲频率),然后由定时器/计数器获得数字值。其优点是用简单电路就能获得高分辨率,抗干扰能力强,但缺点是由于转换精度依赖于积分时间,因此转换速率极低。初期的单片AD转换器大多采用积分型,现在逐次比较型已逐步成为主流。
  2. 逐次比较型:逐次比较型AD由一个比较器和DA转换器通过逐次比较逻辑构成,从MSB开始,顺序地对每一位将输入电压与内置DA转换器输出进行比较,经n次比较而输出数字值。其电路规模属于中等。其优点是速度较高、功耗低,在低分辩率(<12位)时价格便宜,但高精度(>12位)时价格很高。
  3. 并行比较型/串并行比较型:并行比较型AD采用多个比较器,仅作一次比较而实行转换,又称FLash(快速)型。由于转换速率极高,n位的转换需要2n-1个比较器,因此电路规模也极大,价格也高,只适用于视频AD转换器等速度特别高的领域。串并行比较型AD结构上介于并行型和逐次比较型之间,最典型的是由2个n/2位的并行型AD转换器配合DA转换器组成,用两次比较实行转换,所以称为 Half flash(半快速)型。还有分成三步或多步实现AD转换的叫做分级(Multistep/Subrangling)型AD,而从转换时序角度又可称为流水线(Pipelined)型AD,现代的分级型AD中还加入了对多次转换结果作数字运算而修正特性等功能。这类AD速度比逐次比较型高,电路规模比并行型小。
  4. Σ-Δ(Sigma delta)调制型:Σ-Δ型AD由积分器、比较器、1位DA转换器和数字滤波器等组成。原理上近似于积分型,将输入电压转换成时间(脉冲宽度)信号,用数字滤波器处理后得到数字值。电路的数字部分基本上容易单片化,因此容易做到高分辨率。主要用于音频和测量。
  5. 电容阵列逐次比较型:电容阵列逐次比较型AD在内置DA转换器中采用电容矩阵方式,也可称为电荷再分配型。一般的电阻阵列DA转换器中多数电阻的值必须一致,在单芯片上生成高精度的电阻并不容易。如果用电容阵列取代电阻阵列,可以用低廉成本制成高精度单片AD转换器。最近的逐次比较型AD转换器大多为电容阵列式的。
  6. 压频变换型:压频变换型(Voltage-Frequency Converter)是通过间接转换方式实现模数转换的。其原理是首先将输入的模拟信号转换成频率,然 后用计数器将频率转换成数字量。从理论上讲这种AD的分辨率几乎可以无限增加,只要采样的时间能够满足输出频率分辨率要求的累积脉冲个数的宽度。其优点是分辩率高、功耗低、价格低,但是需要外部计数电路共同完成AD转换。

3、ADC主要参数介绍

  1. 分辨率:数字量变化一个最小量时模拟量的变化量,定义为满刻度与2n的比值。分辩率又称精度,通常以数字信号的位数来表示。
  2. 转换速率:完成一次A/D转换所需要时间的倒数,值越大表示转换得越快。积分型AD的转换时间是毫秒级属低速AD,逐次比较型AD是微秒级属中速AD,全并行/串并行型AD可达到纳秒级。
  3. 量化误差:由于AD的有限分辩率而引起的误差,即有限分辩率AD的阶梯状转移特性曲线与无限分辩率AD(理想AD)的转移特 性曲线(直线)之间的最大偏差。通常是1 个或半个最小数字量的模拟变化量,表示为1LSB、1/2LSB。
  4. 偏移误差:输入信号为零时输出信号不为零的值,可外接电位器调至最小。
  5. 满刻度误差:满度输出时对应的输入信号与理想输入信号值之差。
  6. 线性度:实际转换器的转移函数与理想直线的最大偏移。

监测内容ADC选用选用引脚
15V电压ADC1-14通道PC4
2输入电流ADC1-15通道PC5
31.2V电压ADC3-15通道PF5
43.3V电压ADC3-4通道PF6
52.5V电压ADC3-5通道PF7

四、 实验程序

1. 主函数

int main(void)  
{    
    int i;    
    HAL_Init();  
    SystemClock_Config();   //配置系统时钟
    MX_GPIO_Init();          //初始化所有已配置的外围设备
    MX_ADC1_Init();
    MX_ADC3_Init();
    MX_UART4_Init();  
 
    LED_RED_ON;		               //红灯亮
    while (1)
    {	//ADC监控电源
         for(i = 0;i < 100000;i++);
	      for(i = 0;i < 5;i++){
		adc.read(i);
	 }
	 uart4.printf("\x0c");  //清屏                
         uart4.printf("\033[1;32;40m");//字体终端设置为绿色            
         uart4.printf("\r\n\r\nhello! I am iCore3!\r\n\r\n\r\n");
				       //在串口终端打印“Hello! I am iCore3”
        //打印系统供电电压
	 uart4.printf(" [V]     %4.2fV\r\n",adc1_3.value[0]*6);
	 uart4.printf(" [I] 	%3.0fmA\r\n",adc1_3.value[1] / 2* 1000);
	 uart4.printf(" [1.2V]  %4.2fV\r\n",adc1_3.value[2]);
	 uart4.printf(" [3.3V]  %4.2fV\r\n",adc1_3.value[3] * 2);
	 uart4.printf(" [2.5V]  %4
     }
}

2. ADC结构体定义

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc3;
typedef struct  
{  
  ADC__TypeDef                  *Instance;   
//ADC寄存器基地址  
  ADC_InitTypeDef               Init;      
  //ADC所需参数 
  __IO uint32_t                  NbrOfCurrentConversionRank;   
//当前转换列的ADC数 
  DMA_HandleTypeDef             *DMA_Handle;         
//指针DMA处理程序  
  HAL_LockTypeDef                Lock;             
//锁定对象  
  __IO uint32_t                  State;
//ADC通信状态
  __IO uint32_t                 ErrorCode;      
 //ADC错误代码  
} ADC_HandleTypeDef;
typedef struct 
{
  uint32_t Channel;               //指定要配置为ADC常规组的通道。
  uint32_t Rank;                  //指定常规组序列器中的列组,此参数必须是介于Min Data=1和Max Data=16之间的数字
  uint32_t SamplingTime;          //要为选定通道设置的采样时间值。 
  uint32_t Offset;                //保留供将来使用,可设置为0
}ADC_ChannelConfTypeDef;
HAL_StatusTypeDef HAL_ADC_ConfigChannel (ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)

3. ADC相关函数

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)

4. ADC读取数据程序

void sort(unsigned short int a[], int n)
{
int i, j, t;
	//元素从大到小排列
	for (i = 0; i < n - 1; i++) {
		for (j = 0; j < n - i - 1; j++) {
			if (a[j] > a[j + 1]) {
				t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
		}
	}
}
static int read_adc(int channel)
{
int i,k;
unsigned long int temp[20] = {0};
unsigned long int value;
unsigned short int data[100];
ADC_ChannelConfTypeDef channel_config;
unsigned char channel_remap[5] = {ADC_CHANNEL_14,ADC_CHANNEL_15,ADC_CHANNEL_15,ADC_CHANNEL_4,ADC_CHANNEL_5};	
//取得到的100个转换值的中间的20个的平均值作为结果
//连续取20次这样的平均值,再求平均值作为最终结果
channel_config.Channel = channel_remap[channel];
channel_config.Rank = 1;
channel_config.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if(channel == 0 || channel == 1){
		HAL_ADC_ConfigChannel(&hadc1,&channel_config);
}else {
		HAL_ADC_ConfigChannel(&hadc3,&channel_config);
}
for(k = 0;k < 20;k++){		  //取20组数值做滤波
	for(i = 0;i < 100;i++){
	   if(channel == 0 || channel == 1){
		HAL_ADC_Start(&hadc1); //开启ADC1采集通道
		while(!__HAL_ADC_GET_FLAG(&hadc1,ADC_FLAG_EOC));//等待转换结束
		data[i] = HAL_ADC_GetValue(&hadc1);			//将结果保存
	   }else {
		HAL_ADC_Start(&hadc3); //开启ADC3采集通道
		while(!__HAL_ADC_GET_FLAG(&hadc3,ADC_FLAG_EOC));//等待转换结束
		data[i] = HAL_ADC_GetValue(&hadc3);			//将结果保存
	    }
}
	sort(data,100);		  
	for(i = 40;i < 60;i++){	//	对采集到的数值做均值滤波处理
	   temp[k] += data[i];
	}
	   temp[k] = temp[k] / 20;
}
value = 0;
for(k = 0;k < 20;k++){
value += temp[k]; 
}
value /= 20;
adc13.value[channel] = value * ADC_REF / 4096; 
//12位的ADC满量程为2^12=4096,参考电压ADC_REF 为2.483V
return value;
}

五、 实验步骤

六、 实验现象