搜索
查看: 2864|回复: 5

[原创] 【P-NUCLEO-IHM002】移植工程问题解决&串口&外部中断&电机调速

[复制链接]

该用户从未签到

57

主题

374

帖子

7

蝴蝶豆

论坛元老

最后登录
2022-9-9
发表于 2017-8-31 23:15:03 | 显示全部楼层 |阅读模式
    这几天一直都在捣鼓官方SDK中的例程,其中最令我兴奋的是找到了之前移植的个人工程失败的原因。原因是stm32f30x_it.c的SysTick_Handler()函数和stm32f30x_MC_it.c整个文件不能移除,必须被保留。SysTick_Handler()函数的作用是运用系统滴答定时器的计时溢出中断,周期性执行某个程序,如HAL_GPIO_TogglePin()翻转某个LED灯的电平状态,当然,SysTick_Handler()执行的间隔太短,肉眼是看不出LED翻转效果的。官方例程里面的SysTick_Handler()函数里面是TB_Scheduler()函数,涉及到一些电机状态控制和安全控制相关的函数,所以不能去掉。虽然不能去掉,但是可以把SysTick_Handler()整个搬到main.c的最下面,既方便修改,又减少了工程所包含文件的数量。至于stm32f30x_MC_it.c,里面的重要函数是一些定时器中断请求的函数如TIMx_UP_M2_IRQHandler(),也是非常重要不能去掉的。那么我是怎么发现这点的呢,是靠排除法发现的,我在进行STM32开发的时候最看不爽的就是XXXX_it.c结尾的中断服务函数源文件,一般情况下能删则删,不能删则一个个函数移植。在我操作官方SDK的时候不小心误删了stm32f30x_MC_it.c文件,然后电机也不转了,于是我就知道了stm32f30x_MC_it.c这个文件很重要,不能删。
SysTick_Handler必须保留.jpg TB_scheduler函数内部.jpg
    既然移植的工程没有任何问题,那自然就可以开始进行自己的开发了。俗话说调通串口好办事,首要做的肯定是先调通串口以便以后监控各个变量的情况。由于是标准库,我首先想到的是套用正点原子战舰F103ZE的例程,但是初期套用没法调通,花了我将近一个小时,后来我将官方库的串口初始化代码移植过来,总算是成功了。以下是串口初始化代码,供大家参考:
  1. <font size="3">void USART2_Init(int baud)
  2. {
  3.   RCC_APB1PeriphClockCmd(RCC_AHBPeriph_GPIOA|
  4.         RCC_APB1Periph_USART2,ENABLE);
  5.         
  6.         USART_InitStructure.USART_BaudRate=115200;
  7.         USART_InitStructure.USART_WordLength=USART_WordLength_8b;
  8.         USART_InitStructure.USART_StopBits=USART_StopBits_1;
  9.         USART_InitStructure.USART_Parity=USART_Parity_No;
  10.         

  11. USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
  12.         USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
  13.           USART_Init(USART2,&USART_InitStructure);
  14.           USART_Cmd(USART2, ENABLE);
  15.         
  16.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  17.           GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  18.           GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  19.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  20.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  21.   
  22.          GPIO_Init(GPIOA,&GPIO_InitStructure);
  23.   
  24.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  25.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
  26.         GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;
  27.           GPIO_Init(GPIOA,&GPIO_InitStructure);
  28.         
  29.         GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_7);  
  30.         GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_7);
  31.         
  32.         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  33.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
  34.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  35.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  36.         NVIC_Init(&NVIC_InitStructure);
  37. }</font>
复制代码

这里顺便提提,官方的串口初始化函数是用结构体函数指针进行初始化的,串口的各种参数如波特率、校验位、停止位等等,串口的PORT脚和引脚等等都经过三层封装,放在三个不同的文件里,这点跟ST官方的Disco系列开发板的外设初始化程序很像:
另外,初始化函数多次提到了object(对象)这个单词,很容易让人联想到8月22日电机套件直播的时候主持人提到的【面向对象初始化】,并且官方FOC例程里面有诸多类似于XXXX_class.c(对象的实现)、XXXX_private.h(对象的声明)、XXXX_class.h(接口)三大类型文件的分别存放,很容易可以让开发者知道官方想要进行纯C环境下的面向对象开发的意图。这点是好还是不好呢,我也不想作过多评价,免得被社区里某些所谓的【自认为是老工程师的人】指指点点
面向对象程序三大分类.jpg
现在我就贴出部分官方初始化串口的函数:
  1. <font size="3">const USART_InitTypeDef UFCInitHW_str =
  2. {
  3.   USART_SPEED,                         //USART_BaudRate
  4.   USART_WordLength_8b,            //USART_WordLength
  5.   USART_StopBits_1,               //USART_StopBits
  6.   USART_Parity_No,                //USART_Parity
  7.   USART_Mode_Tx,  //USART_Mode
  8.   USART_HardwareFlowControl_None  //USART_HardwareFlowControl
  9. };

  10. USARTParams_t USARTParams_str =
  11. {
  12.   USART,                 // USART
  13.   USART_GPIO_REMAP,      
  14. // USART_REMAP GPIO_NoRemap_USART1 or GPIO_Remap_USART1 ...
  15.   USART_CLK,              // USART_CLK
  16.   USART_RX_GPIO_PORT,    // USART_RxPort
  17.   USART_RX_GPIO_PIN,     // USART_RxPin
  18.   USART_TX_GPIO_PORT,    // USART_TxPort
  19.   USART_TX_GPIO_PIN,     // USART_TxPin
  20.   UI_IRQ_USART,           // IRQ Number
  21.   (USART_InitTypeDef*)(&USARTInitHW_str),       // USART_InitStructure
  22.   (NVIC_InitTypeDef*)(&NVICInitHW_str)         // NVIC_InitStructure
  23. };</font>
复制代码
  1. <font size="3">CUSART_COM USART_NewObject(pUSARTParams_t pUSARTParams)
  2. {
  3.   _CCOM _oCOM;
  4.   _CUSART _oUSART;
  5.   
  6.   _oCOM = (_CCOM)COM_NewObject();

  7.   #ifdef MC_CLASS_DYNAMIC
  8.     _oUSART = (_CUSART)calloc(1,sizeof(_CUSART_t));
  9.   #else
  10.     if (USART_COM_Allocated  < MAX_USART_COM_NUM)
  11.     {
  12.       _oUSART = &USART_COMpool[USART_COM_Allocated++];
  13.     }
  14.     else
  15.     {
  16.       _oUSART = MC_NULL;
  17.     }
  18.   #endif
  19.   
  20.   _oUSART->pDParams_str = pUSARTParams;
  21.   _oCOM->DerivedClass = (void*)_oUSART;
  22.   _oCOM->Methods_str.pStartReceive = &USART_StartReceive;
  23.   _oCOM->Methods_str.pStartTransmit = &USART_StartTransmit;
  24.   
  25.   _oCOM->Methods_str.pIRQ_Handler = &USART_IRQ_Handler;
  26.   Set_UI_IRQ_Handler(pUSARTParams->bUIIRQn, (_CUIIRQ)_oCOM);
  27.   
  28.   //Init Struct communication
  29.   COM_ResetTX((CCOM)_oCOM);
  30.   COM_ResetRX((CCOM)_oCOM);
  31.   
  32.   USART_HWInit(pUSARTParams);
  33.   
  34.   return ((CUSART_COM)_oCOM);
  35. }

  36. void USART_HWInit(pUSARTParams_t pUSARTParams)
  37. {
  38.   GPIO_InitTypeDef GPIO_InitStructure;
  39.   
  40.   /* Enable USART clock: UASRT1 -> APB2, USART2-5 -> APB1 */
  41.   if (pUSARTParams->wUSARTClockSource == RCC_APB2Periph_USART1)
  42.   {
  43.     RCC_APB2PeriphClockCmd(pUSARTParams->wUSARTClockSource, ENABLE);
  44.   }
  45.   else
  46.   {
  47.     RCC_APB1PeriphClockCmd(pUSARTParams->wUSARTClockSource, ENABLE);
  48.   }  
  49.   
  50.   /* USART Init structure */
  51.   /* Configure USART */
  52.   USART_Init(pUSARTParams->USARTx, pUSARTParams->USART_InitStructure);
  53.   
  54.   GPIO_PinAFConfig(pUSARTParams->hRxPort, USART_GPIOPin2Source(pUSARTParams->hRxPin), USART_AF(pUSARTParams->USARTx));
  55.   GPIO_PinAFConfig(pUSARTParams->hTxPort, USART_GPIOPin2Source(pUSARTParams->hTxPin), USART_AF(pUSARTParams->USARTx));
  56.   
  57.   /* Configure Rx, Tx pins */
  58.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  59.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  60.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  61.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  62.   
  63.   GPIO_InitStructure.GPIO_Pin = pUSARTParams->hRxPin;
  64.   GPIO_Init(pUSARTParams->hRxPort, &GPIO_InitStructure);
  65.   
  66.   GPIO_InitStructure.GPIO_Pin = pUSARTParams->hTxPin;
  67.   GPIO_Init(pUSARTParams->hTxPort, &GPIO_InitStructure);
  68.   
  69.   if (pUSARTParams->NVIC_InitStructure->NVIC_IRQChannelCmd == ENABLE)
  70.   {
  71.     /* Enable USART Receive and Transmit interrupts */
  72.     if ((pUSARTParams->USART_InitStructure->USART_Mode & USART_Mode_Rx) == USART_Mode_Rx)
  73.     {
  74.       USART_ITConfig(pUSARTParams->USARTx, USART_IT_RXNE, ENABLE);
  75.     }
  76.     if ((pUSARTParams->USART_InitStructure->USART_Mode & USART_Mode_Tx) == USART_Mode_Tx)
  77.     {
  78.       USART_ITConfig(pUSARTParams->USARTx, USART_IT_TXE, DISABLE);
  79.     }
  80.     /* Enable the USARTy Interrupt */
  81.     NVIC_Init(pUSARTParams->NVIC_InitStructure);
  82.   }
  83.   
  84.   /* Enable the USART */
  85.   USART_Cmd(pUSARTParams->USARTx, ENABLE);
  86. }</font>
复制代码

好不好用大家心中有数,大家喜欢正点原子风格还是官方Disco风格,自己决定吧。
       除了串口以外,外部中断也是必须调通的一个外设。官方例程的按键处理程序是while轮询,但是我认为,电机控制这种事情,还是用外部中断最好。顺便说说F3XX的外部中断,用SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource13)函数替代了F103的GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13),为了找相关资料,又忙活了一下午。以下是外部中断初始化和中断服务函数
  1. <font size="3">void EXTI13_Init()
  2. {
  3.          EXTI_InitTypeDef EXTI_InitStructure;
  4.          NVIC_InitTypeDef NVIC_InitStructure;
  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         
  7.         RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOC|
  8.         RCC_APB2Periph_SYSCFG, ENABLE);
  9.         GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
  10.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
  11.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
  12.         GPIO_Init(GPIOC,&GPIO_InitStructure);
  13.         
  14.         SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource13);
  15.           EXTI_InitStructure.EXTI_Line=EXTI_Line13;
  16.           EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;        
  17.           EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
  18.           EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  19.           EXTI_Init(&EXTI_InitStructure);

  20.          NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
  21.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
  22.           NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
  23.           NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;        
  24.           NVIC_Init(&NVIC_InitStructure);
  25. }
  26. </font>
复制代码
  1. <font size="3">void EXTI15_10_IRQHandler()
  2. {         
  3.         if(EXTI_GetITStatus(EXTI_Line13) != RESET)
  4.   {
  5.                 flag=0;
  6.                 cont++;
  7.                 if(cont>5)cont=0;
  8.                 printf("进入外部中断,cont=%d\n",cont);        
  9.                 EXTI_ClearITPendingBit(EXTI_Line13);
  10.         }
  11. }</font>
复制代码

调通了外部中断之后,就可以结合之前的电机调速Task,进行实验了。每按一次按键,电机速度提升3000转,到了13000转之后速度重新归为1000转:
  1. <font size="3">int main()
  2. {   
  3.         STM32F3_64MHz_Internal();
  4.   MCboot(oMCI,oMCT);
  5.   SysTick_Configuration();
  6.         EXTI13_Init();
  7.         USART2_Init(115200);
  8.         printf("STM32社区 电机套件试用活动\n");
  9.   //MCI_StartMotor(oMCI[M1]);
  10.   while(1)
  11.   {  
  12.                
  13.                 switch(cont)
  14.                 {
  15.                         case 1:
  16.                         if(flag==0)
  17.                         {
  18.                                 flag=1;
  19.                                 MCI_StartMotor(oMCI[M1]);
  20.                                 MCI_ExecSpeedRamp(oMCI[0],1000/6,1000);
  21.                                 printf("设置电机转速为1000\n");
  22.                         }
  23.                         break;
  24.                         case 2:
  25.                         if(flag==0)
  26.                         {
  27.                                 flag=1;
  28.                                 MCI_StartMotor(oMCI[M1]);
  29.                                 MCI_ExecSpeedRamp(oMCI[0],4000/6,1000);
  30.                                 printf("设置电机转速为4000\n");
  31.                         }
  32.                         break;
  33.                         case 3:
  34.                         if(flag==0)
  35.                         {
  36.                                 flag=1;
  37.                                 MCI_StartMotor(oMCI[M1]);
  38.                                 MCI_ExecSpeedRamp(oMCI[0],7000/6,1000);
  39.                                 printf("设置电机转速为7000\n");
  40.                         }
  41.                         break;
  42.                         case 4:
  43.                         if(flag==0)
  44.                         {
  45.                                 flag=1;
  46.                                 MCI_StartMotor(oMCI[M1]);
  47.                                 MCI_ExecSpeedRamp(oMCI[0],10000/6,1000);
  48.                                 printf("设置电机转速为10000\n");
  49.                         }
  50.                         break;
  51.                         case 5:
  52.                         if(flag==0)
  53.                         {
  54.                                 flag=1;
  55.                                 MCI_StartMotor(oMCI[M1]);
  56.                                 MCI_ExecSpeedRamp(oMCI[0],13000/6,1000);
  57.                                 printf("设置电机转速为13000\n");
  58.                         }
  59.                         break;
  60.                 }

  61.   }
  62. }</font>
复制代码


串口通信.jpg
1.gif
    上传工程文件。 电机套件工程.zip (3.79 MB, 下载次数: 94)
回复

使用道具 举报

该用户从未签到

1

主题

16

帖子

0

蝴蝶豆

初级会员

最后登录
2019-7-29
发表于 2017-9-11 15:15:47 | 显示全部楼层
厉害了我狼哥
回复 支持 反对

使用道具 举报

该用户从未签到

4

主题

12

帖子

2

蝴蝶豆

初级会员

最后登录
2018-7-3
发表于 2017-12-12 15:56:06 | 显示全部楼层
楼主牛啊
回复

使用道具 举报

该用户从未签到

0

主题

13

帖子

0

蝴蝶豆

初级会员

最后登录
2018-12-13
发表于 2018-3-15 22:22:02 | 显示全部楼层
顶,好的帖子别沉
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

2

帖子

0

蝴蝶豆

新手上路

最后登录
2018-11-4
发表于 2018-11-4 22:10:46 | 显示全部楼层
下载试试
回复

使用道具 举报

该用户从未签到

0

主题

9

帖子

0

蝴蝶豆

新手上路

最后登录
2019-1-16
发表于 2018-11-9 18:26:37 | 显示全部楼层
xiexie !!!!!
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-5-9 09:39 , Processed in 0.194282 second(s), 38 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表