本文使用环境:
电脑:windows10
主控:W806(240MHZ)
兼容:W800 W801
编译环境:平头哥的CDK
注意:本文默认已经搭建好平台。
参考文章:
W806-ADC-PWM-TIM尝鲜
写在前面:
最近有比较多的同学问到了多路ADC如何使用的问题,官方的demo只给出了单路ADC,因此本文就详细讲解一下。
一、文档
首先翻阅芯片的手册,查看ADC对应的端口和特性,这里直接查看上一篇文章的第1.1小节。
二、编程
2.1、定义ADC端口和ADC的结构体
定义单片机所有的ADC端口,一共有4个外接端口和一个电压、一个温度(共6个)。对应的IO注释在定义后面。在main
函数定义如下:
//ADC
/*
* ADC_CHANNEL_0 : channel 0
* ADC_CHANNEL_1 : channel 1
* ADC_CHANNEL_2 : channel 2
* ADC_CHANNEL_3 : channel 3
* ADC_CHANNEL_0_1 : channel 0 and channel 1 differential input
* ADC_CHANNEL_2_3 : channel 2 and channel 3 differential input */
/* 307hz ~ 2khz */
//ADC编号
#define ADC_1 0 //PA1
#define ADC_2 1 //PA4
#define ADC_3 2 //PA3
#define ADC_4 3 //PA2
#define ADC_TEMP 4
#define ADC_VOL 5
//一共6个端口所以定义六个结构体数组
ADC_HandleTypeDef hadc[6];
注意: 由于官方的demo存在bug,所以需要做如下修改,否者下面的步骤编译会报错。
在wm_adc.h
文件中,添加如下定义ADC_CHANNEL_VOL
。注意下图可以看出adc的频率在307-2000
之间,记住这里。
#define ADC_CHANNEL_0 ADC_ANA_CR_CH_0
#define ADC_CHANNEL_1 ADC_ANA_CR_CH_1
#define ADC_CHANNEL_2 ADC_ANA_CR_CH_2
#define ADC_CHANNEL_3 ADC_ANA_CR_CH_3
#define ADC_CHANNEL_0_1 ADC_ANA_CR_CH_8
#define ADC_CHANNEL_2_3 ADC_ANA_CR_CH_9
//add by zxx start
#define ADC_CHANNEL_VOL ADC_ANA_CR_CH_VOL
//add by zxx end
#define ADC_CHANNEL_TEMP ADC_ANA_CR_CH_TEMP
#define ADC_CHANNEL_OFFSET ADC_ANA_CR_CH_OFFSET
#define ADC_FREQ_MIN 307
#define ADC_FREQ_MAX 2000
2.2、修改初始化代码
官方的demo只给出了一个init函数,若需要使用多个需要自己单独多次修改,不是很方便,因此对官方的demo稍加修改。函数入口参数改为adc_num
和freq
,分别表示通道数和频率。通道数使用2.1小节定义的宏,频率直接写数字就行。
注意: 从上小节可以看出频率要保持在307-2000之间。但手册
写的是1000,我也不是很理解。
static void ADC_Init(uint32_t adc_num, uint32_t freq)
{
/*
//ADC_CHANNEL_0 : PA1
//ADC_CHANNEL_1 : PA4
//ADC_CHANNEL_2 : PA3
//ADC_CHANNEL_3 : PA2
//ADC_CHANNEL_0_1 : PA1 and PA4
//ADC_CHANNEL_2_3 : PA3 and PA2
#define ADC_CHANNEL_0 ADC_ANA_CR_CH_0
#define ADC_CHANNEL_1 ADC_ANA_CR_CH_1
#define ADC_CHANNEL_2 ADC_ANA_CR_CH_2
#define ADC_CHANNEL_3 ADC_ANA_CR_CH_3
#define ADC_CHANNEL_0_1 ADC_ANA_CR_CH_8
#define ADC_CHANNEL_2_3 ADC_ANA_CR_CH_9
#define ADC_CHANNEL_VOL ADC_ANA_CR_CH_VOL
#define ADC_CHANNEL_TEMP ADC_ANA_CR_CH_TEMP
#define ADC_CHANNEL_OFFSET ADC_ANA_CR_CH_OFFSET
*/
uint32_t ADC_CHANNEL;
/* 307hz ~ 2khz */
switch(adc_num)
{
case 0: ADC_CHANNEL = ADC_CHANNEL_0; break; //PA1
case 1: ADC_CHANNEL = ADC_CHANNEL_1; break; //PA4
case 2: ADC_CHANNEL = ADC_CHANNEL_2; break; //PA3
case 3: ADC_CHANNEL = ADC_CHANNEL_3; break; //PA2
case 4: ADC_CHANNEL = ADC_CHANNEL_TEMP; break;
case 5: ADC_CHANNEL = ADC_CHANNEL_VOL; break;
default : printf("adc init ADC_CHANNEL err, The number of channels is not between 0 and 3 \r\n");return; break;
}
if(freq > 2000 || freq < 304)
printf("adc freq too larger than 2khz or too lower than 307hz...please check...\n");
hadc[adc_num].Instance = ADC;
hadc[adc_num].Init.channel = ADC_CHANNEL;
hadc[adc_num].Init.freq = freq;
if (HAL_ADC_Init(&hadc[adc_num]) != HAL_OK)
{
printf("adc init err...\n");
}
}
2.3、主函数
int main(void)
{
int value[6] = {0};
SystemClock_Config(CPU_CLK_160M);
printf("enter main\r\n");
ADC_Init(ADC_1,1000);
ADC_Init(ADC_2,1000);
ADC_Init(ADC_3,1000);
ADC_Init(ADC_4,1000);
ADC_Init(ADC_TEMP,1000);
ADC_Init(ADC_VOL,1000);
while (1)
{
value[0] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_1]);
value[1] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_2]);
value[2] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_3]);
value[3] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_4]);
value[4] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_TEMP]);
value[5] = HAL_ADC_GET_INPUT_VOLTAGE(&hadc[ADC_VOL]);
for(int i=0;i<6;i++)
printf("value%d: = %d ",i,value[i]);
printf("\n");
HAL_Delay(1000);
}
}
三、测试
下载程序到开发板,并串口输出: