描述:用adc连续采集11路模拟信号,并由dma传输到内存。adc配置为扫描并且连续转换模式,adc的时钟配置为12mhz。在每次转换结束后,由dma循环将转换的数据传输到内存中。adc可以连续采集n次求平均值。最后通过串口传输出最后转换的结果。
程序如下:
#i nclude “stm32f10x.h” //这个头文件包括stm32f10x所有外围寄存器、位、内存映射的定义
#i nclude “eval.h” //头文件(包括串口、按键、led的函数声明)
#i nclude “systickdelay.h”
#i nclude “uart_interface.h”
#i nclude
#define n 50 //每通道采50次
#define m 12 //为12个通道
vu16 ad_value[n][m]; //用来存放adc转换结果,也是dma的目标地址
vu16 after_filter[m]; //用来存放求平均值之后的结果
int i;
void gpio_configuration(void)
{
gpio_inittypedef gpio_initstructure;
gpio_initstructure.gpio_pin = gpio_pin_9;
gpio_initstructure.gpio_mode = gpio_mode_af_pp; //因为usart1管脚是以复用的形式接到gpio口上的,所以使用复用推挽式输出
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
gpio_init(gpioa, &gpio_initstructure);
gpio_initstructure.gpio_pin = gpio_pin_10;
gpio_initstructure.gpio_mode = gpio_mode_in_floating;
gpio_init(gpioa, &gpio_initstructure);
//pa0/1/2 作为模拟通道输入引脚
gpio_initstructure.gpio_pin = gpio_pin_0| gpio_pin_1|gpio_pin_2|gpio_pin_3;
gpio_initstructure.gpio_mode = gpio_mode_ain; //模拟输入引脚
gpio_init(gpioa, &gpio_initstructure);
//pb0/1 作为模拟通道输入引脚
gpio_initstructure.gpio_pin = gpio_pin_0|gpio_pin_1;
gpio_initstructure.gpio_mode = gpio_mode_ain; //模拟输入引脚
gpio_init(gpiob, &gpio_initstructure);
//pc0/1/2/3/4/5 作为模拟通道输入引脚
gpio_initstructure.gpio_pin = gpio_pin_0|gpio_pin_1|gpio_pin_2|gpio_pin_3|gpio_pin_4|gpio_pin_5;
gpio_initstructure.gpio_mode = gpio_mode_ain; //模拟输入引脚
gpio_init(gpioc, &gpio_initstructure);
}
}
void rcc_configuration(void)
{
errorstatus hsestartupstatus;
rcc_deinit(); //rcc 系统复位
rcc_hseconfig(rcc_hse_on); //开启hse
hsestartupstatus = rcc_waitforhsestartup(); //等待hse准备好
if(hsestartupstatus == success)
{
flash_prefetchbuffercmd(flash_prefetchbuffer_enable); //enable prefetch buffer
flash_setlatency(flash_latency_2); //set 2 latency cycles
rcc_hclkconfig(rcc_sysclk_div1); //ahb clock = sysclk
rcc_pclk2config(rcc_hclk_div1); //apb2 clock = hclk
rcc_pclk1config(rcc_hclk_div2); //apb1 clock = hclk/2
rcc_pllconfig(rcc_pllsource_hse_div1, rcc_pllmul_6); //pllclk = 12mhz * 6 = 72 mhz
rcc_pllcmd(enable); //enable pll
while(rcc_getflagstatus(rcc_flag_pllrdy) == reset); //wait till pll is ready
rcc_sysclkconfig(rcc_sysclksource_pllclk); //select pll as system clock source
while(rcc_getsysclksource() != 0x08); //wait till pll is used as system clock source
rcc_apb2periphclockcmd(rcc_apb2periph_gpioa|rcc_apb2periph_gpiob
| rcc_apb2periph_gpioc |rcc_apb2periph_adc1 | rcc_apb2periph_afio |rcc_apb2periph_usart1, enable ); //使能adc1通道时钟,各个管脚时钟
rcc_adcclkconfig(rcc_pclk2_div6); //72m/6=12,adc最大时间不能超过14m
rcc_ahbperiphclockcmd(rcc_ahbperiph_dma1, enable); //使能dma传输
}
}
void adc1_configuration(void)
{
adc_inittypedef adc_initstructure;
adc_deinit(adc1); //将外设 adc1 的全部寄存器重设为缺省值
adc_initstructure.adc_mode = adc_mode_independent; //adc工作模式:adc1和adc2工作在独立模式
adc_initstructure.adc_scanconvmode =enable; //模数转换工作在扫描模式
adc_initstructure.adc_continuousconvmode = enable; //模数转换工作在连续转换模式
adc_initstructure.adc_externaltrigconv = adc_externaltrigconv_none; //外部触发转换关闭
adc_initstructure.adc_dataalign = adc_dataalign_right; //adc数据右对齐
adc_initstructure.adc_nbrofchannel = m; //顺序进行规则转换的adc通道的数目
adc_init(adc1, &adc_initstructure); //根据adc_initstruct中指定的参数初始化外设adcx的寄存器
//设置指定adc的规则组通道,设置它们的转化顺序和采样时间
//adc1,adc通道x,规则采样顺序值为y,采样时间为239.5周期
adc_regularchannelconfig(adc1, adc_channel_0, 1, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_1, 2, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_2, 3, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_3, 4, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_8, 5, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_9, 6, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_10, 7, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_11, 8, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_12, 9, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_13, 10, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_14, 11, adc_sampletime_239cycles5 );
adc_regularchannelconfig(adc1, adc_channel_15, 12, adc_sampletime_239cycles5 );
// 开启adc的dma支持(要实现dma功能,还需独立配置dma通道等参数)
adc_dmacmd(adc1, enable);
adc_cmd(adc1, enable); //使能指定的adc1
adc_resetcalibration(adc1); //复位指定的adc1的校准寄存器
while(adc_getresetcalibrationstatu
本文引用地址: http://www.21ic.com/app/mcu/201810/778451.htm
s(adc1)); //获取adc1复位校准寄存器的状态,设置状态则等待
adc_startcalibration(adc1); //开始指定adc1的校准状态
while(adc_getcalibrationstatus(adc1)); //获取指定adc1的校准程序,设置状态则等待
}
void dma_configuration(void)
{
dma_inittypedef dma_initstructure;
dma_deinit(dma1_channel1); //将dma的通道1寄存器重设为缺省值
dma_initstructure.dma_peripheralbaseaddr = (u32)&adc1-》dr; //dma外设adc基地址
dma_initstructure.dma_memorybaseaddr = (u32)&ad_value; //dma内存基地址
dma_initstructure.dma_dir = dma_dir_peripheralsrc; //内存作为数据传输的目的地
dma_initstructure.dma_buffersize = n*m; //dma通道的dma缓存的大小
dma_initstructure.dma_peripheralinc = dma_peripheralinc_disable; //外设地址寄存器不变
dma_initstructure.dma_memoryinc = dma_memoryinc_enable; //内存地址寄存器递增
dma_initstructure.dma_peripheraldatasize = dma_peripheraldatasize_halfword; //数据宽度为16位
dma_initstructure.dma_memorydatasize = dma_memorydatasize_halfword; //数据宽度为16位
dma_initstructure.dma_mode = dma_mode_circular; //工作在循环缓存模式
dma_initstructure.dma_priority = dma_priority_high; //dma通道 x拥有高优先级
dma_initstructure.dma_m2m = dma_m2m_disable; //dma通道x没有设置为内存到内存传输
dma_init(dma1_channel1, &dma_initstructure); //根据dma_initstruct中指定的参数初始化dma的通道
}
//配置所有外设
void init_all_periph(void)
{
rcc_configuration();
gpio_configuration();
adc1_configuration();
dma_configuration();
//usart1_configuration();
usart_configuration(9600);
}
u16 getvolt(u16 advalue)
{
return (u16)(advalue * 330 / 4096); //求的结果扩大了100倍,方便下面求出小数
}
void filter(void)
{
int sum = 0;
u8 count;
for(i=0;i《12;i++)
{
for ( count=0;count
{
sum += ad_value[count][i];
}
after_filter[i]=sum/n;
sum=0;
}
}
int main(void)
{
u16 value[m];
init_all_periph();
systick_initaize();
adc_softwarestartconvcmd(adc1, enable);
dma_cmd(dma1_channel1, enable); //启动dma通道
while(1)
{
while(usart_getflagstatus(usart1,usart_flag_txe)==reset);//等待传输完成否则第一位数据容易丢失
filter();
for(i=0;i《12;i++)
{
value[i]= getvolt(after_filter[i]);
printf(“value[%d]:\t%d.%dv\n”,i,value[i]/100,value[i]0) ;
delay_ms(100);
}
}
}
总结
该程序中的两个宏定义,m和n,分别代表有多少个通道,每个通道转换多少次,可以修改其值。
曾出现的问题:配置时钟时要知道外部晶振是多少,以便准确配置时钟。将转换值由二进制转换为十进制时,要先扩大100倍,方便显示小数。最后串口输出时在 printf语句之前加这句代码,防止输出的第一位数据丢失:while(usart_getflagstatus(usart1,usart_flag_txe)==reset);
AI来了 25种方式将颠覆现代商业
PRL封面!本源量子与中科大团队合作在半导体量子计算方向获新进展
全景展现汽车创新,高通汽车技术与合作峰会将于下周举行
美国对人脸识别的态度急转直下 对其发出了禁令
Global Foundries与IBM将共同生产32纳米芯片
基于STM32单片机ADC连续采集和DMA循环转换
自动驾驶未来何在
音箱选购基础知识问与答
15A μModule稳压器通过将12V高效转换为1V来解决热问题
奥比中光亮相Japan IT Week春季展
金航标电子员工感悟分享 在倔强中成长
iSuppli预测09年LED背光成为面板产业救世主
电子皮肤让机器人“感受”它们检测到的信号
48V轻度混合系统的出现
JBL增加PartyBox类别 耐世特合作推出道路和轮胎检测软件
X-ray在线检测设备在LED灯条检测中的应用
Digi-Key Electronics宣布与GLF Integrated Power达成全新全球分销合作关系
艾欧史密斯中国2019届研发专题——史密斯工程师招聘
Google Pixel 3用户报告了手机电池的主要问题
三星将与中国电信联手推出一款折叠屏手机 可中间折叠