你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 ADC USART DMA彻底应用

[复制链接]
TopMars 提问时间:2011-10-6 14:56 /
 
学习STM32的ADC转换,在开发板上写程序调试。
四个任务:
1.AD以中断方式(单次)采集一路
2.AD以中断方式连续采集四路
3.AD以DMA方式采集一路,DMA深度为一级
4.AD以DMA方式采集四路,每路DMA深度为28级,并滤波,说明滤波原理。
总结:
第一个任务:ADC以中断方式采集一路ADC,通过配置ADC_InitStructure结构体中的ADC_ScanConvMode,它规定模数转换工作在扫描模式(多通道)还是单次模式(单通道),
ADC_InitStructure.ADC_ScanConvMode=DISABLE,为单通道单次模式。
ADC_ContinuousConvMode,定转换是连续还是单次,ADC_ContinuousConvMode=DISABLE
为单次,ADC_NbrOfChangnel规定ADC规则转换的通道数。ADC_NbrOfChannel=1;//开启1个通道数。
ADC_RegularChannelConfig(ADC1,ADC_Channel_13, 1,ADC_SampleTime_55Cycles5);设置指定规则组的通道的采样顺序和转换时间。这里以为只有一路通道,采用的是PC3引脚,对应的通道数是13通道,采样顺序也就是1,。
ADC_Cmd(ADC1,ENABLE);使能ADC
ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);开启ADC转换结束中断。
ADC_ResetCalibration(ADC1);//重置校验寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //等待重置校验成功
ADC_StartCalibration(ADC1);//开始ADC校验
while(ADC_GetCalibrationStatus(ADC1));//等待ADC校验好
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发开始转换
因为ADC有一个16位的规则组数据寄存器(ADC_DR),采用一路转换时可以不用通过DMA传输。这里就没有配置DMA。
void ADC_IRQHandler(void)
{
       ADCConvertedValue=ADC_GetConversionValue(ADC1); 
       ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);            
}
当一次转换结束,DAC产生中断,在中断函数里,读取ADC_DR寄存器中的值,一定清除中断标志位。
采集出来的数据是16进制数,要经过处理,变成10进制数,具体如下:
(value*100/4096)*33,value是从寄存器读出来的十六进制的数据,经过此变换后就变成10进制数,是个整数,我们通过串口显示的时候要把小树部分也要显示出来则有:((value*100/4096)*33)/1000,整数部分。
((value*100/4096)*33)%1000/100,((value*100/4096)*33)%100/10),小数部分,
串口配置,我是通过STM32上的串口1与PC机通讯的,具体配置如下:
void USART_Configuration(void)
{
       USART_InitTypeDef USART_InitStructure;
       USART_InitStructure.USART_BaudRate=9600;波特率9600
     USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位数据位
     USART_InitStructure.USART_StopBits=USART_StopBits_1;1个停止位
     USART_InitStructure.USART_Parity=USART_Parity_No;无奇偶校验
     USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
       USART_Init(USART1,&USART_InitStructure);初始化串口配置
       USART_Cmd(USART1,ENABLE);使能串口
}
int fputc(int ch,FILE *f)
{
       USART_SendData(USART1, (u8)ch);
       while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)//检查发送是否完成
       {
       }
       return ch;
}此函数,是把printf输出函数定向到USART。
第一个任务大概就是这个过程,在后面的任务有相同之处,就不重复叙述了。
第二个任务:ADC以中断方式连续采集四路。
首先配置4路模拟输入,我配置的是PC0、PC1、PC2、PC3四个IO口,输入方式为模拟输入,速度采用2M,它们对应的ADC通道分别是10、11、12、13通道。
在第一个任务说了,ADC规则转换多路采样时,ADC的数据寄存器只有一个16位寄存器,所以必须采用DMA来传输数据,DMA配置如下:
DMA_InitStructure.DMA_PeripheralBaseAddr=DR_ADDRESS; //DMA对应的外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&Buf; //内存存储基地址,定义的一个数组
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //DMA转换模式为SRC模式,由外设搬移到内存
DMA_InitStructure.DMA_BufferSize=4; // DMA缓存大小,4个(设置DMA在传输时缓冲区的长度)
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移(设置DMA的外设递增模式)
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //关闭接收一次数据后,目标内存地址后移(设置DMA的内存递增模式)
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//定义外设数据长度
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;
//循环模式开启,Buf写满后,自动回到初始地址开始传输
DMA_InitStructure.DMA_Priority=DMA_Priority_High;//优先级高
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
ADC配置:
//ADC配置
       ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立转换模式
     ADC_InitStructure.ADC_ScanConvMode=ENABLE;//开启扫描模式
     ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换模式
     ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//ADC外部开关,关闭状态
     ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//对齐方式,右对齐方式
     ADC_InitStructure.ADC_NbrOfChannel=4;//开启通道数,4个
       ADC_Init(ADC1,&ADC_InitStructure);//初始化ADC
       ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5);
       ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_55Cycles5);
       ADC_RegularChannelConfig(ADC1, ADC_Channel_12,3,ADC_SampleTime_55Cycles5);
       ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_55Cycles5);;
       //ADC通道组,第10、11、12、13个通道,采样顺序分别是1,2,3,4转换时间55.5个周期
       ADC_DMACmd(ADC1, ENABLE);//使能ADC1模块DMA
       ADC_Cmd(ADC1, ENABLE);//打开ADC1
       ADC_ResetCalibration(ADC1);//重置ADC1校准寄存器
       while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校准重置完成
       ADC_StartCalibration(ADC1);//开始ADC1校准
       while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校准完成
       ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1软件开始转换
中断是采用DMA中断,当DMA第一轮传输结束时,设一个标志位,当标志位为1时,表明第一轮转化和传输完成,此时就可以读取数组中的数据,经过处理就可以通过串口显示出来。
void DMAChannel1_IRQHandler(void)
{         
              ADC_DMA_OK=1;
              DMA_ClearITPendingBit(DMA1_IT_TC1);              
}中断函数。
第二个任务大概就这样子。
第三个任务:AD以DMA方式采集一路,DMA深度为一级。
这个任务不难,关键要理解到DMA深度,用自己的语言来理解哈DMA深度吧,当ADC以一路采集时,ADC转换完成就自动把转换结果通过DMA传给目的地址,如果传输一次结束DMA就产生中断的话,DMA的深度就为一级,如果连续传输N次,DMA的深度就位N级,当然这个N是又范围的,因为受目的地址的内存大小控制和数据宽度,这个大家应该豆明白的。
这个任务在第一个任务的基础上我通过DMA传输,意思是AD配置没什么区别。DMA配置和第二个任务的区别就是DMA_BufferSize的宽度不同。
#define DR_ADDRESS   (u32)0x4001244c ADC的地址
#define DMA_Count    1   DMA深度,也就是连续传输的次数
#define ADC_Channle 1 ADC通道
数据处理和串口通讯这里不重复叙述。DMA中断和任务二的类似。
第四个任务:AD以DMA方式采集四路,每路DMA深度为128级,并滤波,说明滤波原理。
这个任务和是个综合性任务,只要弄懂前面三个任务,难点是再如何滤波,开始的时候我也不知道怎么滤波,同事提醒我才知道怎么滤波的,我大概说哈我的理解,把四路通道采集的数据分别放到四个数组中,然后给他来个排序,降序,升序都行,把首位两个数丢掉,然后加起来求平均值。但是我这里因为DMA的深度为128级,也就是四个通道分别采样了128次,大家都知道,数据越多,求平均值就越准确,所以我就没有采用什么排序法了,直接给他们分别求平均值,具体如下:
#define DR_ADDRESS   (u32)0x4001244c ADC的地址
#define DMA_Count    128   DMA深度,也就是连续传输的次数
#define ADC_Channle 4 ADC通道
       for(i=0;i
收藏 评论1 发布时间:2011-10-6 14:56

举报

1个回答
ljfljfljf123 回答时间:2012-5-7 20:59:36

回复:STM32 ADC USART DMA彻底应用

正需要呢,谢谢
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版