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

如何利用P-NUCLEO-IHM001转动带霍尔的BLDC电机(更新中)  

[复制链接]
dear祝子 发布时间:2017-8-19 09:43
本帖最后由 dzzwoaizi 于 2017-8-25 08:40 编辑
$ I  ?, P1 h; a) a) v
, g' f6 d  g- o# o* J, {, v9 o/ `其实,看ST的官方demo有一种使人头大的感觉,各种代码各种库集合到一起,不容易上手,顾打算利用P-NUCLEO-IHM001转动手中带HALL的BLDC电机。原本是要在搞一套无位置BLDC的代码,但是苦耐于P-NUCLEO-IHM001是利用ADC检测反动势的(我利用的是比较器检测过零点)
7 C0 e( O( y, o/==============分割线===================/
# X# p1 D5 k$ J带位置传感器的BLDC点击控制算法是比较简单的,只需要搞懂HALL位置和通电顺序的对应关系就能将电机转起来。# R/ o" A  v! K5 K/ s; J; `3 j
BLDC_HALL所以的单片机资源
" |- g9 H" \( ~4 {) D: N3 g0 ]+ W  ?(1)高级定时器TIM1+ADC+DMA% s+ `( Z2 ~/ g0 ~, D/ v
         ST在这一块做的堪称完美,高级定时器的CC4通道用来触发ADC采集数据,ADC采集完成之后利用DAM搬运到数组中,这所有的流程都是硬件完成的,程序只需要读取数组中的ADC采样值就可以了,这样大大节省了单片机的运算时间。3 R5 q7 A* z; O
(2)3路外部中断连接HALL
7 |* w6 h6 v$ w0 G% [6 ?         这里你当然也可以利用TIM接口与高级定时器直接连接在一起,利用硬件在换向,但是这种方式不便于移植算法。相反,ST的每个IO口都可以作为外部中断口来用,我们只需要随便3个IO就可以了。  F  A2 D% O0 H  P, L
利用以上资源就能够将电机转起来。# e4 s1 r# U9 U

" f2 V7 V" d3 i0 p2 i5 B( m流程分3步,1.搭建STM32F3开发环境  2.底层代码编写,3.算法如何调试
' z, W% d; H+ w' I2 E
" n0 {/ U4 H$ ?& @% {1 [$ L& M昨天抽了个时间建立了一个工程,找不到flash加载了,很是郁闷,经过一番查找,终于找打解决办法。因为我装个KEIL4.7,可能是因为我之前卸载KEIL5从新装pach包的时候装错地址了。解决办法:在KEIL4安装目录下找到E:\2.software\mdk470\ARM\Flash  把里面的 STM32XXX.FLM文件复制到你安装的LEIL5的\ARM\Flash中既可以了。附件为刚建好的工程模板, 2.STM32F302RB_BLDC.zip (7.54 MB, 下载次数: 302)
赞 收藏 11 评论33 发布时间:2017-8-19 09:43

举报

33个回答
dear祝子 最优答案 回答时间:2017-8-22 17:39:00
本帖最后由 dzzwoaizi 于 2017-9-2 13:12 编辑
' i: I9 K! c" D3 [$ w+ w如何利用高级定时器CC4通道来触发ADC采集数据在利用DMA搬运到数组之中的。' y3 E/ r/ [  s' S% Q/ Z7 ?# f
说实话,第一次用STM32F3系列的单片机,和F0的还不是非常一样,我还花了很多时间将寄存器手册看了几个重要的外设。仔细阅读了STM32F的寄存器手册之后发现只有注入组才能用CC4触发ADC,如图为ADC外部信号触发的图
( `8 d! z) {, ?" {% E0 o" U YQ%~K@PT7FB$MMSQF]6ZN5X.png 9%0`_CEZHGM9SGP60D20REC.png
! V& q: B/ ]5 n) w这个是规则组和注入阻外部触发信号选择,我选择的规则组,这里用TIM1_CC1触发ADC采集,所以相对应的代码配置如下:
# d3 T% V/ {  O  u. A1 q1 Q
  1. /* Initialize ADC structure */
    ( R3 v7 v' K: C/ n" g
  2.         ADC_StructInit(&ADC_InitStructure);7 G8 X3 c8 W* g( O7 e
  3.         ADC_InitStructure.ADC_Resolution                   = ADC_Resolution_12b;
    2 o. f4 @- ]* U* }( ~# N
  4.         ADC_InitStructure.ADC_ContinuousConvMode          = DISABLE;                                                                                                                                            //单通道模式
      c8 c. v0 z; T2 J1 m
  5.         ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge; ; //设置上升沿触发中断
    3 K  N$ F/ Z5 t7 c9 r7 D
  6.         ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0 ;            //ADC触发源
    8 [4 q" s5 _  {* W" ^- c
  7.         ADC_InitStructure.ADC_DataAlign                    = ADC_DataAlign_Right;                                                                                           //数据右对齐
    % R1 n% J0 O3 p. E6 v( @' ^: w4 `. A
  8.         ADC_InitStructure.ADC_OverrunMode                                         = ADC_OverrunMode_Enable;                                                                                 //数据溢出禁用+ L% K# C. f# {2 G
  9.         ADC_InitStructure.ADC_AutoInjMode                                         = ADC_AutoInjec_Disable;      
    $ Q- l8 z3 D& f( F6 h4 }& q9 e/ r
  10.         ADC_InitStructure.ADC_NbrOfRegChannel                         = 2;        8 ~% {5 o5 }7 H1 [
  11.         ADC_Init(ADC1, &ADC_InitStructure);
复制代码
在看一下通道的选择:(电压,温度)
: O' N, f" ], N9 v' q9 r E@RMUX)H%SHUYDUE5_0Z749.png 1X$%O)QP2}}[F5Z3RBP)V`N.png * a, S3 c( k1 m+ G* B1 r6 l
可以看到这里用的是是PA1和PC2
) g9 T9 q; j# d- A8 Q" b6 v- x
  1. /* ADC1 regular channel7 configuration */
    : j6 m8 J; i6 J* c' C* Q
  2.         ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_7Cycles5);
      b2 P0 |2 ~9 e3 X0 ]" j
  3.         ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_7Cycles5);
复制代码
然后在使能ADC切配置DMA使能就OK了!$ t0 n! p3 r; c. c1 i) \
  1. /* ADC1 DMA Enable */0 A+ P9 V! ?  [- z
  2.         ADC_DMACmd(ADC1, ENABLE);
    3 W/ \3 j) w( y$ c+ i1 ?
  3.         ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);
    % l3 h  \) F! Z- M% e1 i
  4.         /* Enable ADC1 */
    ; D  @: Y1 N& b8 E& P: q
  5.         ADC_Cmd(ADC1, ENABLE);
    5 y0 e! [9 m7 H& Y
  6.         /* wait for ADRDY */
    ) F5 }$ Z  ~1 Q
  7.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
    : i" T$ j  i# r2 l. `
  8.         /* Start ADC1 Software Conversion */ 0 H  z6 W+ @3 J
  9.         ADC_StartConversion(ADC1);
复制代码
DMA配置如下!! n( L3 O9 u; F
  1.     DMA_InitTypeDef DMA_InitStructure;  . y8 `9 Q( ^: f) O: i% ^( D
  2.           NVIC_InitTypeDef NVIC_InitStructure;
    ' u7 \' w0 k# b$ j4 z' L
  3.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);              //使能DMA时钟  7 a7 m7 g, Z6 ~1 X  f
  4.   
    0 a7 ~' t+ Y, _$ g# [- S8 ~3 }9 c
  5.     DMA_DeInit(DMA1_Channel1);                                      //复位DMA1_channel1  
    % S; e; n) s" h& Z
  6.     DMA_StructInit(&DMA_InitStructure);                            //初始化DMA结构体  
    2 k$ X% j( Q$ d1 j" M7 ^
  7.   % w3 x+ ]9 g( H- u  c
  8.     DMA_InitStructure.DMA_PeripheralBaseAddr         = (uint32_t) &(ADC1->DR);//取值的外设地址  
      S. o. Z) G9 h  H5 r9 J
  9.     DMA_InitStructure.DMA_MemoryBaseAddr                         = (uint32_t)&ADC_Tab[0];//缓存数据数组起始地址  ) ~3 b3 G* X! |0 H+ i3 f
  10.     DMA_InitStructure.DMA_DIR                                                                 = DMA_DIR_PeripheralSRC;//DMA方向:外设作为数据源  1 r- N# d6 W9 s" D
  11.     DMA_InitStructure.DMA_BufferSize                                         = 2;                                            //DMA缓存数组大小设置  ; @0 H( y+ P" F& E/ h% a4 C% A
  12.     DMA_InitStructure.DMA_PeripheralInc                                 = DMA_PeripheralInc_Disable;//外设地址递增禁用  
    ) K+ H/ V: }7 z' V
  13.     DMA_InitStructure.DMA_MemoryInc                                         = DMA_MemoryInc_Enable; //内存地址递增  , _: ]1 ~4 [' D$ o
  14.     DMA_InitStructure.DMA_PeripheralDataSize         = DMA_PeripheralDataSize_HalfWord;//外设取值大小设置为Halfword  1 y1 W: w* T0 p, ]) r. ?( E
  15.     DMA_InitStructure.DMA_MemoryDataSize                         =        DMA_MemoryDataSize_HalfWord ;//数据大小设置为Halfword  9 L" r( q4 [: ~5 l5 z0 g1 i3 ~
  16.     DMA_InitStructure.DMA_Mode                                                                 = DMA_Mode_Circular;    //DMA循环模式,即完成后重新开始覆盖  
    " w4 `2 `5 h8 J" s* z
  17.     DMA_InitStructure.DMA_Priority                                                 = DMA_Priority_High;    //DMA优先级设置为高          + f( t7 {& \/ U6 q! v  c! L; r- W
  18.     DMA_InitStructure.DMA_M2M                                                                 = DISABLE;              //内存到内存禁用  
    ! g7 V0 X/ I8 O& u
  19.     DMA_Init(DMA1_Channel1, &DMA_InitStructure);  
    / [8 o, G/ S2 Q- A  Q3 ]% T5 E
  20.   
    / D9 ?/ {: r( M9 `- }
  21.     //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);. C' I7 M- J" I5 y, J
  22.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn ;
    / y( y1 m& J, Q6 L( N  O4 |2 D
  23.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;4 ~- x( F' E% X) [
  24.     NVIC_InitStructure.NVIC_IRQChannelSubPriority =0 ;
      C# V8 s8 G+ O! O9 O& R) f
  25.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;( W: k+ Y; x4 O% P' h4 J
  26.     NVIC_Init(&NVIC_InitStructure);  
      T% H0 D- O9 S5 w4 L* \
  27.                 . w& j. q6 |& S: C& X  S
  28.     DMA_ITConfig(DMA1_Channel1, DMA1_FLAG_TC1, ENABLE);                  //使能DMA中断  3 R/ _! j8 O5 c8 U
  29.     DMA_ClearITPendingBit(DMA1_FLAG_TC1);                                //清除一次DMA中断标志  ' C! _) R% ?% Q9 {8 }" }0 R
  30.     DMA_Cmd(DMA1_Channel1, ENABLE);  //使能DMA1
复制代码
DMA配置的时候一定要注意外设地址和缓存数据起始地址及缓存数据的大小不要设置错了,否则采集数据也会出现错位!我这里采集的是两路,所以定义的是  uint16_t ADC_Tab[2];            //ADC储存  B: u0 D4 q% W& _6 r
这里BUF对应的数据如下 :ADC_Tab[0]存放的电压的采集值。ADC_Tab[1]存放的温度的采集值+ z( q1 {# ], W# R
你只需要在主程序中调用者两个值就可以了!
% B: Q3 \6 `* w+ N# q3 |* X) @$ u, W! W

4 D9 I, z6 I; [* ^  G附件为自己调试好的程序,有兴趣的可以自己下载看看,里面基本的功能都调试完成,代码的硬件就是P-NUCLEO-IHM001,, e# ]2 ~: S4 w/ S/ g- Q
视频会晚些上传给大家看看效果。 4.STM32F302RB_BLDC.zip (7.89 MB, 下载次数: 2243)
ya496928541 回答时间:2019-3-19 17:43:41
dzzwoaizi 发表于 2017-8-22 17:396 A( x4 t% ?/ o; T, V# q
本帖最后由 dzzwoaizi 于 2017-9-2 13:12 编辑 1 c# ?% e) H' ^: t3 g
如何利用高级定时器CC4通道来触发ADC采集数据在利用DMA搬 ...
1 {7 s* ^; ~& c. k$ t
谢谢楼主分享
我是胡工 回答时间:2020-8-2 09:43:41
http://microchip.eefocus.com/module/forum/thread-5254-1-1.html) y0 z' l" p3 u2 T6 q# n
请问这个是什么文档?404了
张亚飞 回答时间:2017-8-19 11:00:25
贪玩不回家 回答时间:2017-10-21 15:17:50
1767355084 回答时间:2018-3-15 22:25:34
后悔看到的有点晚
dear祝子 回答时间:2018-3-16 08:25:30
1767355084 发表于 2018-3-15 22:25
2 u" u9 W/ {) ]后悔看到的有点晚

. @- N( U: g8 z1 `遇到同行了相互学习
joegong 回答时间:2018-3-28 09:27:43
感谢  无私奉献!
z258121131 回答时间:2018-4-24 19:45:56
楼主威武
ewewe3b1a1b 回答时间:2018-5-12 15:11:06
多谢
2 U# {* ?% T( o0 Y+ _. s7 z$ K! Y
james-210864 回答时间:2018-5-17 20:14:15
xiexie
james-210864 回答时间:2018-5-18 08:46:52
xiexie
james-210864 回答时间:2018-5-18 08:48:20
xiexie
toobe5201 回答时间:2018-6-5 14:40:58
感謝分享
+ s1 X. ^+ D( e  B  Z' ]正在學習電動機驅動
asdfg221111 回答时间:2018-6-6 20:37:33
感谢楼主,持续学习中
asdfg221111 回答时间:2018-6-7 08:24:02
谢谢楼主
123下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版