|
STM32f103的数电采集电路的TIMER定时器的 使用与时序控制的程序 STM32 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。1 l/ k/ d# v% x, T( n% M
0 k) ]2 k; b" v6 I( K通用定时器设置的一般步骤可以总结为如下几个步骤:
0 c' \0 x9 H) X; [& i% `) L/ W3 j! A( Q* m1 t
1.定时器时钟使能
1 M* {$ D& F) p3 {- [3 k
5 v2 H$ A- }- `2.设置定时参数
, f6 K2 q5 ^6 B, w0 i6 B) W! |4 Y7 x' O+ U
3.定时器工作方式初始化
" } s5 }; G \1 J0 D+ c3 Y7 c: U. @/ S) o! Z6 c1 W2 ^
4.定时器中断方式使能( C7 V: b9 d( n) |7 H
! J* X9 k# A0 `5.开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)- {7 {) f7 F( L, y6 d$ D
7 L6 Z Y$ d3 r5 ?3 E8 v; Q
6.使能定时器8 p+ B' t+ p7 |: n5 Y
y K$ l4 n) e
7.编写中断处理函数
" D. `: f& `+ a% b6 X4 ]/ H
4 V- v. I( W3 \% A2 X; a" r前端采集模块采用了TIM4定时器作为USART1串口的定时发送,定时间隔为10ms,采用中断方式在中断服务函数里面使能USART1的DMA通道,使USART1能自动完成数据的发送任务,减少CPU的工作量和大大减少中断转跳时间,同时和ADC采样时序是相互独立的,不受ADC采样的间隔影响,确保了数据间隔时间的稳定性。
+ E7 U+ \3 ^: l- h# W* A4 J6 j- [cpp] view plain copy7 s& U4 i6 h" C5 a }; ~5 ^7 D
- //通用定时器中断初始化
+ u8 E& q( G6 y" i1 K; Z - //这里时钟选择为APB1的2倍,而APB1为36M " s( @* E5 f1 r9 R/ y2 B9 g
- //arr:自动重装值。 ! z- C h! Q& R' b2 n9 V
- //psc:时钟预分频数
; ~, j" u) i8 d, q - //这里使用的是定时器4!
8 _" {+ x8 W! N2 z. m$ `7 J - void TIM4_Int_Init(u16 arr,u16 psc) ( ]) B8 F0 L1 M+ x3 b* y7 `( Z& s
- {
, D. ]* D2 w1 w' q: a - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
. e2 v# j/ [2 d: {8 U! x - NVIC_InitTypeDef NVIC_InitStructure;
( I' Z$ C Q1 m+ E) c( V) j -
* `5 T3 R9 C! M3 O& G+ K* Q( j; Q) v - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能 + } {9 h, }' {6 j: x
-
% ^7 F' q4 [! z. V - TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
7 r; b5 s% A+ C$ x% I0 z - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- G9 t* K4 h& h- R - TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim + c* h: p7 U0 v. Y6 {
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
$ r/ p; H2 ]5 a5 g- s$ f; \ - TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
( j, v0 F4 ], L* b7 V8 \ -
. }; ?: C; K1 D0 w - TIM_ITConfig( //使能或者失能指定的TIM中断 % _ q, V* Z% M. j
- TIM4, //TIM4
% w. u; Z+ X" m/ Z2 P2 O - TIM_IT_Update ,
j1 P. |7 ? \) ~7 `; b$ U - ENABLE //使能
4 G1 |$ n5 I1 n& d - ); 2 `( ?( o) f6 g: m/ n" ^
- NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中断 4 L a$ E: j4 H! ]& w% F4 @
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 : ~# u3 g4 }: e
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
0 x! [9 u0 _3 j* d. k! ] - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 2 ?# E* B+ w1 z# X4 ~
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
3 s7 D/ U, e( w" ? - U8 Z r N' Y( X! V7 Y
- TIM_Cmd(TIM4, ENABLE); //使能TIMx外设
$ y0 h/ k+ b& `: N( R -
: C0 C* {. i4 z - } - f8 {6 s/ G/ B4 k6 d- u
- [cpp] view plain copy
) }5 w" r( O$ p3 S( n - uint8_t HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; //16进制字符表
; r+ H6 p. v; O. ~* q9 G4 j% | - 4 @) r/ S; D! s. O7 \8 ]8 b
- void TIM4_IRQHandler(void) //TIM4中断 0 `/ s# ~) E& a6 l4 [8 q! s
- { % k7 h9 d% E7 N, @/ R! K
- if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 " J+ l9 N) O% ^, l! o
- {
8 D$ R4 l# Z/ p/ J6 m - <span style="white-space:pre"> </span>//进行数据读取并转换成需要发送的字符 - c7 B- q# l$ Q! v" @
- AdcChar[0] = HexTable[(adcValue>>12)&0x0f];
8 Y- T3 W3 L3 G3 H; a! N! l - AdcChar[1] = HexTable[(adcValue>>8)&0x0f]; 8 H, _, b! ]0 N1 {; T. O' F8 D
- AdcChar[2] = HexTable[(adcValue>>4)&0x0f]; * Q J& Q4 x% i A& Z* \% r
- AdcChar[3] = HexTable[(adcValue)&0x0f]; ! D0 ~. q0 r' o, l7 }. D3 |
- //将数据加载到串口发送数组
1 W' M }6 \' [+ x - SendBuff[0] = AdcChar[0];
& L8 f8 a2 y" G! ~, P% j9 B3 g - SendBuff[1] = AdcChar[1]; . f6 ~, t3 r- b- ~) V$ G8 _
- SendBuff[2] = AdcChar[2];
2 `, g @, c: \; W$ m$ S - SendBuff[3] = AdcChar[3]; ) I2 t. R$ ~' X+ t
- //USB_SendString("Connect to stm32 test the max lenght and more over 22 Byte."); 7 B' _4 K$ s X) a5 z2 O, a
- DMA_USART_Enable(DMA1_Channel4); 8 I7 F( }1 C& u8 ^) F! Z7 D& J
- }
/ v0 ^! _; z. I( b7 E5 m& d - TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
5 X: e: |1 n1 E: }! H. X: V3 } - }
: l4 |) T- s M; s% L: E e" D
复制代码 为了保证数据的采样率的稳定性,这里使用TIM4进行采样率的控制。TIM4定时一到,立即进入中断响应,在中断函数里,将ADC采样的数组空间进行数据读取,并加载在USART发送数据中 V# d' P) V k& w; a# W
这里的数据报文采用了进制的字符形式发送,通信数据报文如下:(这里是双通道ADC的报文,单通道的报文则取前5位)
( M$ t" I, q) [+ S$ B6 F- W5 k
; y" |7 F4 ]2 g$ m0 n) y注意:Data7、Data6、Data5、Data、Data3、Data2、Data1、Data0 是字符形式
0 u# Q( ^$ l9 @) Geg:ADC1 数据 1024 mV => 0x400
" _. s0 l# G- gADC2 数据 2048 mV => 0x8006 M2 @) \7 j$ }! u- U" U8 O) Z
- f' G+ ~: V' [9 [ o1 B8 c数据报文发送:P0400Q0800( v' h4 z5 ^" T
. c( U9 m. B" |+ e
2 T% o: a" S6 @, s. D- ~5 e
+ K) y( z: A: L6 t
0 z( c/ p/ I- T2 B$ l [
|