在做有ad模块项目的时候遇到几个问题:
1, adc配合dma采样规则是怎样的。
2, adc在dma采可否不连续采样,以提高有效采样使用率和降低功耗。
3, 如何提高有效利用率和降低功耗,并减少cpu的占用时间。
4, adc的如何多通道采样。
针对以上几个问题做解答。
adc的采样模式主要分两个:规则采样和注入采样。规则模式可采样16个通道,注入模式最多只能4个通道。
配合dma使用时主要是用规则采样模式。在初始化时配置采样端口为规则采样通道即可如下:
列:dc_regularchannelconfig(adc1, adc_channel_0, 1, adc_sampletime_239cycles5);
端口1为规则采样的第一位,239.5的adc时钟采样周期。
adc在dma下可以不连续采样,既采样一定数据后,关闭adc及dma通道。但是这样子存在一些问题。dma的存储的变量数组中的数据会出现错位问题。
测试过很多方法,包括adc和dma一起重新初始化,依然无法解决这个问题。系统只进行一次初始化时,dma数据无错位现象。 但是对于长时间不关机的产品来说,缺少了几分可靠性。网上也有相关的评测,adc用dma工作在强电磁的环境中可能会输出丢失部分数据的可能。
这里就想到了用中断的方式,进行采样。无法用规则模式,因为只能用单次采样触发中断。由于无法确定第一个通道,这样同样会遇到数据错位的现象。所以这里使用注入模式进行中断出发。
有以下几个优点:
1,可以最多4路为一组采样,每组采样结束后才产生一次中断,减少了进中断的次数。
2,在读取数据时几路通道都是预先配置好的。某个变量存放指定某个指定通道。这样永远不可能出现错位现象。
由以总结 在4路及以下通道进行采样时,首选注入模式进行中断采样。超过4路及不是长时间工作的产品(几天以上不断电)可以考虑。
单路采样时,这两种方法都很可靠。
最近刚好在学习ucosii系统,并参考了下通用驱动程序开发。附上adc驱动代码,希望有所帮助。
提示,在使用某路通道 只要 该通道宏定义置1就可以了。
#defineadcx_channel0_en1//adcx通道11:便能,0:失能
注意: 在使用注入模式时 最多使能4个通道。
1 /*
2 ********************************************************************************
3 * uc/os-ii
4 * ad采样驱动程序设计
5 * arm cortex-m3 port
6 *
7 * file : adcxdrv.c
8 * version : v1.0
9 * by : 王宏强
10 *
11 * for : stm32f10x
12 * mode : thumb2
13 * toolchain :
14 * realview microcontroller development kit (mdk)
15 * keil uvision
16 * description : 定时器驱动
17 * 占用adcx(adc1,adc2)
18 *
19 * 1,dma规则模式(可靠性低,多路用此模式) 加宏定义 #define adc_dma
20 * 2,4路以下,用注入模式(可靠性高,占资源少)
21 *
22 * adcxopen
23 * adcxclose
24 * adcxwrite
25 * adcxread
26 * adcxioctl
27 * adcxinstall
28 * adcxnuinstall
29 * date : 2012.05.22
30 *******************************************************************************/
31
32 #include “adcxdrv.h”
33
34 //dma采样缓冲区
35 static volatile int16u adc_convertedvaluetab[max_ad_sample_counter] = {0};
36 static int16u adcxbuff[channel_count] = {0}; //缓冲区数据平均值
37 static int16u index = 0;
38
39 #ifdef ucosii
40 static os_event *adcsem;
41 static int8u err;
42 #endif
43
44 //总采样时间(单位ms) = 读样个数 * 采样1个值所用时间 / 72mhz * 1000
45 //static int16u sampingtime = (int16u)(channel_count * adcx_sample_count *
46 // 239 * 5 / 9e3 + 1);
47
48 /* private macro -------------------------------------------------------------*/
49 /* private variables ---------------------------------------------------------*/
50 adc_inittypedef adc_initstructure;
51 dma_inittypedef dma_initstructure;
52 nvic_inittypedef nvic_initstructure;
53
54
55
56 /*******************************************************************************
57 * function name :int16u getsampletemp(int16u order)
58 * description :获取采样到的数据,并进行平均
59 * input :order:通道序列号
60 * output :返回本通道 采样平均值
61 * other :
62 * date :2012.05.23 14:48:23
63 *******************************************************************************/
64 static int16u getsamplevalue(int16u order)
65 {
66 u32 sum = 0;
67 u16 i = order;
68
69 if (order 》= channel_count) return 0; //序列号超出范围
70
71 for (i = order; i 《 max_ad_sample_counter; i+=channel_count)
72 {
73 sum += adc_convertedvaluetab[i];
74 }
75 sum /= adcx_sample_count;
76
77 return (u16)sum;
78 }
79
80 void startadc(functionalstate stat)
81 {
82 if (stat == enable) index = 0;
83
84 adc_itconfig(adcx, adc_it_jeoc, stat);
85 adc_cmd(adcx, stat);
86 }
87
88
89 /*******************************************************************************
90 * function name :static int32s adcxopen(void *pd)
91 * description :
92 * input :
93 * output :
94 * other :
95 * date :2012.05.23 10:25:06
96 *******************************************************************************/
97 static int32s adcxopen(void *pd)
98 {
99 gpio_inittypedef gpio_initstructure;
100 int32u rccapb = 0;
101 int16u gpiopin = 0;
102
103 /* enable peripheral clocks ----------------------------------------------*/
104 /* enable dma1 and dma2 clocks */
105 rcc_ahbperiphclockcmd(rcc_ahbperiph_dmax, enable);
106
107
108 #if adcx_gpiox_1_en
109 rccapb |= rcc_apbxperiph_gpiox_1;
110 #endif
111
112 #if adcx_gpiox_2_en
113 rccapb |= rcc_apbxperiph_gpiox_2;
114 #endif
115
116 #if adcx_gpiox_3_en
117 rccapb |= rcc_apbxperiph_gpiox_3;
118 #endif
119
120 rccapb |= rcc_apbxperiph_adcx;
121 rcc_apb2periphclockcmd(rccapb, enable);
122 rcc_adcclkconfig(rcc_pclk2_div8);
123
124
125 #if adcx_gpiox_1_en
126 gpiopin = 0;
127 #if adcx_channel0_en
128 gpiopin |= adcx_gpiox_pin_ch0;
129 #endif
130 #if adcx_channel1_en
131 gpiopin |= adcx_gpiox_pin_ch1;
132 #endif
133 #if adcx_channel2_en
134 gpiopin |= adcx_gpiox_pin_ch2;
135 #endif
136 #if adcx_channel3_en
137 gpiopin |= adcx_gpiox_pin_ch3;
138 #endif
139 #if adcx_channel4_en
140 gpiopin |= adcx_gpiox_pin_ch4;
141 #endif
142 #if adcx_channel5_en
143 gpiopin |= adcx_gpiox_pin_ch5;
144 #endif
145 #if adcx_channel6_en
146 gpiopin |= adcx_gpiox_pin_ch6;
147 #endif
148 #if adcx_channel7_en
149 gpiopin |= adcx_gpiox_pin_ch7;
150 #endif
151 gpio_initstructure.gpio_pin = gpiopin;
152 gpio_initstructure.gpio_mode = gpio_mode_ain;
153 gpio_init(adcx_gpiox_1, &gpio_initstructure);
154 #endif
155
156
新手设计的电路到底能挑多少毛病?电路纠错+详细分析
安全带使用规范越来越严格 提高使用率安防有责
巧妙设计声控电子门铃
苹果iPhone真的无法摆脱刘海么?
负载的电功率有功和无功的区别分析
ADC配合DMA采样规则是怎样的?
多核对嵌入式设计原则造成哪些影响
起因于RTN的SRAM误操作进行观测并模拟的方法
如今正在发生的是“物联网正在吃掉支付”
pcb板的热膨胀系数是什么意思啊?怎么测量出来的?
AMD三季度净利增超3倍!
iOS 版微信7.0.5 版本更新,这次更新又有什么新的变动呢?
变频调速电机原理_变频调速电机的优点
关于无线电力测温的方式有哪些?
探索热光刻技术在金属纳米制造中的应用
时频分析和激光多普勒频谱分解技术诊断皮肤血管并发症
阿里Lindorm数据库联手Hightopo开启物联超融合存储模式
谷东科技推出两款全新的工业级AR终端
智能照明在商用行业的应用
器件很简单Datasheet有无无所谓这些电子设计误区你进了么