|
本帖最后由 sun-2034138 于 2016-10-14 16:02 编辑 双路ad同时触发的的代码。应用adc,dma,tim。用的不是hal库而是老版本的固件库和寄存器操作来进行的。f103实测 7 H0 z' D% J: I) z STM32 的通用定时器是一个通过可编程预分频器( PSC)驱动的 16 位自动装载计数器( CNT)" F; O- A) A; W" J8 C' P 构成。 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波 形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形 周期可以在几个微秒到几个毫秒间调整。 STM32 的每个通用定时器都是完全独立的,没有互相. ~9 z' o7 @9 v5 ]: C0 J! J. p$ G 共享的任何资源。 STM3 的通用 TIMx (TIM2、 TIM3、 TIM4 和 TIM5)定时器功能包括: 1)16 位向上、向下、向上/向下自动装载计数器( TIMx_CNT)。 2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~, T0 f+ m4 f7 Z+ f% p% u: W 65535 之间的任意数值。 3) 4 个独立通道( TIMx_CH1~4),这些通道可以用来作为: A.输入捕获( H8 c' g! m' {" j$ b B.输出比较9 s! u) X( t' l% i) N3 Y% U/ N2 X C. PWM 生成(边缘或中间对齐模式)% N6 f" k5 Z6 V9 q; ` D.单脉冲模式输出 4)可使用外部信号( TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外1 R/ t6 k/ |4 X' n+ V" C' W 一个定时器)的同步电路。& P* Y+ E0 E; g, m$ P1 O 5)如下事件发生时产生中断/DMA: A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)) y" _& R& e U6 H' `8 c4 q S! S) T B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)) R6 ~% ^! h& S! g( n0 l5 { C.输入捕获% d9 m1 g) L- d% a D.输出比较. S4 d3 p6 L8 N* P E.支持针对定位的增量(正交)编码器和霍尔传感器电路* J3 m7 {6 {: Z F.触发输入作为外部时钟或者按周期的电流管理8 P; Z6 j; q1 U1 ~$ ]* u; r5 w4 a tim主要寄存器 CR1 DIER PSC 这三个寄存器是基础;7 S, |- Y( V# x" ~; X8 ` 定时器的时钟来源 内部时钟(用cube看时钟树最方便了),外部输入脚,外部触发输入,内部触发输入(用其他定时器做预分频);& L- P: C% A8 l2 b% s& e 有一点值得注意的是也是很多人忽略的问题!ARR实际上是两个寄存器,他同串口的那个USART->DR的类型都是影子寄存器(类似寄存器还有几个呢)所以更新时间根据CR1的APRE位状态看是否更新,不详说看手册; SR寄存器看更新; ' J, Q" r2 Y& I8 _6 w4 g 5 q& B. O7 I$ \, [# _6 _3 h4 A pwm是我最常用的一种功能,先说说这个。要想控制pwm:1 F. f/ N/ |7 k 1.看好时钟源和使能; 2.看是否复用,如果复用开启afio看映射的对不对AFIO->MAPR;" S0 i; z% j) [4 h 3.设置好ARR:自动装载数值(对于初学者来说就是你打算让他一次数多少个数); 4.设置好PSC:预分频(对于初学者来说就是用内部时钟确定数一个数多久),更新的话看CR1的APRE位,不是你改了当时就更新的!!!* K' }& f& G- S3 E' A- `8 _6 k) f 5.CR1:使能还有你用的到的就打钩~;3 @" t8 z- ~/ e& p" s/ ~ 6.CCMR1/2:分为两层 每8位控制一个通道!道理和配置gpio没啥区别。简单说下吧,当时我看这个也搞了好久。 CC1S[1:0]:捕获/比较1 (方向和引脚的选择,输出的话没啥说的就是你要输出的引脚,输入的话比如映射在TL1,2或者TRC上。对于初学者的困惑可能就是TL1是啥了,这个您看通用定时器框图,芯片手册上那个大图)pwm肯定输输出。 OC1FE: 输出比较1 快速使能 ~~~~~~这个是触发输入的 ,就是看灵敏性吧。一般我都默认,还能当个防骚扰~~~~ OC1PE: 输出比较1预装载使能:随时写入TIMx_CCR1寄存器是否当即生效; OC1M[2:0]:输出比较1模式:这个对于pwm来说只能是110或者111, R$ z; S, ^9 A: ? OC1CE:输出比较1清0使能 ~~~~~~~~~~这个oc1ref在哪里呢? 捕获比较寄存器和输出控制器之间。这个东西是可以做触发另一个定时器的。什么pwm1还是2不过是电平的变化而已。 7.CCER:只有两位CCXP(我都是默认高电平有效,不知道你想咋用呢) CCXE(必须为1因为输出)" m0 K( x4 k4 O3 ]" Z2 j! m* v: l O 8.CCR1-4:傻子开始数数了 ~~~ (这个除ARR里面的数就是你的占空比了)/ e0 T& ]) n- u& i 9.高级的才看BDTR寄存器呢不管你想咋设置其他为moe必须为1才能是pwm;% F* a6 u4 d4 T9 h4 J3 y. ^ . n; a% [3 I, O- q8 t( [) u8 x! K/ E) V $ ^2 N& m; P: i- q0 Y 之后 之后就有pwm了。。。别问我为啥因为刚刚都使能了。 这样配置一遍寄存器就是新手也对这个一定有不少了解了,具体什么的功能看看手册吧 之后分享一个双定时器同事dma触发双路adc的代码吧 想玩的朋友直接添加中断服务函数就可以了。rct6的 绝对可以用~~~7 [% I c) N% l k* ]4 f" \ ' h: }3 Q2 T; v H, r2 L# c6 C void Adc_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; , ~/ ?" o7 E6 O2 M( a, E$ A, D DMA_InitTypeDef DMA_InitStructure; 8 ~# @5 V. W* H5 r TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;& j8 H! j) N {9 c5 w, u3 l' C) Y RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //ʱÖÓʹÄÜ /************************************tim2*****************************************/ TIM_TimeBaseStructure.TIM_Period = 9999; //ÉèÖÃÔÚÏÂÒ»¸ö¸üÐÂʼþ×°Èë»î¶¯µÄ×Ô¶¯ÖØ×°ÔؼĴæÆ÷ÖÜÆÚµÄÖµ ¼ÆÊýµ½10000Ϊ1s: ]" T/ I7 }; G* A" Q8 l& B TIM_TimeBaseStructure.TIM_Prescaler =7199; //ÉèÖÃÓÃÀ´×÷ΪTIMxʱÖÓÆµÂʳýÊýµÄÔ¤·ÖƵֵ 10KhzµÄ¼ÆÊýƵÂÊ TIM_TimeBaseStructure.TIM_ClockDivision = 0; //ÉèÖÃʱÖÓ·Ö¸î:TDTS = Tck_tim# e" G: O8 t0 t TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMÏòÉϼÆÊýģʽ TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //¸ù¾ÝTIM_TimeBaseInitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯TIMxµÄʱ¼ä»ùÊýµ¥Î» ! x# F8 h) E, R6 P6 t9 Y0 ]' U TIM_ITConfig( //ʹÄÜ»òÕßʧÄÜÖ¸¶¨µÄTIMÖÐ¶Ï TIM2, //TIM2( Y) ]# [# Q5 Q* i% B+ | TIM_IT_Update , DISABLE //ʹÄÜ ); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3ÖÐ¶Ï NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //ÏÈÕ¼ÓÅÏȼ¶0¼¶: U# b" f0 a4 C7 E2 E2 K, w NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //´ÓÓÅÏȼ¶3¼¶ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀ±»Ê¹ÄÜ- s9 ]( R" a; m NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝNVIC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèNVIC¼Ä´æÆ÷ TIM_Cmd(TIM2,DISABLE); //ʹÄÜTIMxÍâÉè /************************************tim3*****************************************/ TIM_TimeBaseStructure.TIM_Prescaler= 7199; //100k TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;- B2 Y2 I' V0 J6 f% k, @ TIM_TimeBaseStructure.TIM_Period= 30; //; N5 ~! ]) l' c1 F% W! t( w6 O TIM_TimeBaseStructure.TIM_ClockDivision= 0;( ^) u! c! z' \3 k: @ TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;0 W& g9 k: C4 t" f2 |% {6 ~" S: ~ TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);! P2 ?" i; f) g9 l- U TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update); TIM_ARRPreloadConfig(TIM3,ENABLE);7 h. b( Z e; ]5 H TIM_Cmd(TIM3,DISABLE); TIM_UpdateDisableConfig(TIM3,ENABLE); TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);, t; ^) u7 P6 R+ ? RCC->AHBENR |=1<<0; // dma1 RCC->APB2ENR |=1<<4; // GPIOC . ^0 k0 K9 U& ]1 K6 b7 ^ GPIOA->CRL |=0XFFFFF000; // PC 0 1 2 INPUT DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR; DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)ADC_buff; " ~' k* K6 M. i. T' y DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;* E4 j( s3 u" w+ E+ L DMA_InitStructure.DMA_BufferSize=adccnt; DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;5 H8 G% L2 d: ~, f- Q DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word ; DMA_InitStructure.DMA_Mode=DMA_Mode_Circular; DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;' ^# e8 `% {# T) S; ]# @ DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;/ B, t- d. N0 Z/ m- K8 M) y DMA_Init(DMA1_Channel1,&DMA_InitStructure);$ n: N5 {6 n& O% @3 E+ L! S7 T DMA_Cmd(DMA1_Channel1,ENABLE); DMA_ITConfig(DMA1_Channel1,DMA_CCR1_TCIE,ENABLE); //chuanshu wancheng RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2|RCC_APB2Periph_ADC3,ENABLE); //ʹÄÜADC1ͨµÀʱÖÓ RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ÉèÖÃADC·ÖƵÒò×Ó6 72M/6=12,ADC×î´óʱ¼ä²»Äܳ¬¹ý14M //mode3 u6 r- [2 {# r [9 R' @5 H 1 S+ _3 b1 C; q; D# M4 ? ADC1->CR1 = 0x00060020;/ E$ x" i3 \" u) W) q* q ADC1->CR2 = 0x00180100; // 0x00180100; ->0x00080100 ÓÉÍⲿʼþÆô¶¯¸ÃΪ²»ÐèÒªÍⲿʼþÆô¶¯! _5 Z' @% P. j, C: p& a( Z ADC_Cmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC19 H, ]: G& B* n9 ~3 ?" ~ ADC_ResetCalibration(ADC1); //ʹÄܸ´Î»Ð£×¼5 H4 b0 l' ]2 H. l* P+ V6 m while(ADC_GetResetCalibrationStatus(ADC1)); //µÈ´ý¸´Î»Ð£×¼½áÊø1 z) X' A+ {5 Z/ f/ E+ _ ADC_StartCalibration(ADC1); //¿ªÆôADУ׼ while(ADC_GetCalibrationStatus(ADC1)); //µÈ´ýУ׼½áÊø0 x: O* C* |) ~! u ADC2->CR1 = 0x00000000;4 V; p3 p/ N0 k& ~ ADC2->CR1|= 1<<5; ADC2->CR2 = 0x001E0100; ADC_Cmd(ADC2, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1# ?9 V9 I* o- }9 L ADC_ResetCalibration(ADC2); //ʹÄܸ´Î»Ð£×¼* E3 `% A X/ Y5 E0 ]) B# i8 B while(ADC_GetResetCalibrationStatus(ADC2)); //µÈ´ý¸´Î»Ð£×¼½áÊø/ Z# Q. [1 m# R5 C ADC_StartCalibration(ADC2); //¿ªÆôADУ׼: [. B" B6 A) v+ T while(ADC_GetCalibrationStatus(ADC2)); //µÈ´ýУ׼½áÊø ADC_RegularChannelConfig(ADC1, ADC_Channel_10,1,ADC_SampleTime_55Cycles5); //ADC1,ADCͨµÀ,²ÉÑùʱ¼äΪ239.5ÖÜÆÚ ADC_RegularChannelConfig(ADC2, ADC_Channel_11,1,ADC_SampleTime_55Cycles5); //ADC1,ADCͨµÀ,²ÉÑùʱ¼äΪ239.5ÖÜÆÚ 1 d8 R8 N5 p; h g# J6 u NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; //ʹÄܰ´¼üËùÔÚµÄÍⲿÖжÏͨµÀ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //ÏÈÕ¼ÓÅÏȼ¶2¼¶ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //´ÓÓÅÏȼ¶1¼¶ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //ʹÄÜÍⲿÖжÏͨµÀ- f- R6 V* p( G1 a3 K1 @% j0 V d NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝNVIC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèNVIC¼Ä´æÆ÷ 5 `6 H; M2 `. g, C) S //long i=0x 13833572189; H4 o. A% ?0 {5 J/ Q } $ x! H6 k' _. q4 Q3 i3 j D) y8 ? 以下都是摘抄的笔记,好记性不如烂笔头就收藏了下来.代码能不能用我不知道 。 发布的时候字数太多发布上去了....我把连接弄来...还有好几个例程呢! http://blog.sina.com.cn/s/blog_81e410670100wkd8.html7 F* d7 e" `! V# h5 M 其实,PWM模块还可以有很多花样可以玩,比方在异常时(如CPU时钟有问题),可以紧急关闭输出,以免发生电路烧毁等严重事故。 着重补充的是有的时候你在选择管脚的时候是需要注意afio的,选择全映射还是半映射什么的,一定要看好。不然闹的根本不行不行的。 而且这个不出波形的时候是一定要查看内部寄存器的如果没有问题,那么也要多多注意你选择的周期问题!!!!!! |
| 感谢分享! |
![]() ![]() 多谢 |
| 103的 提醒一下大家 |
| 学习了 |
![]() ![]() ![]() ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() :):):):):) |
| 谢谢分享,学习了。 |
| 学习了,多谢分享 |
| 学习了 |
| 注释乱码了 |
微信公众号
手机版