Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178146
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2016-02-01 12:35
个人简介

不断超越自己,将更强大!

文章分类

全部博文(35)

文章存档

2022年(1)

2017年(5)

2016年(29)

我的朋友

分类: 嵌入式

2016-05-02 21:27:47

        电子时代,硬件在突飞猛进的发展,频率不断上升,目前的STM32系列,Cortex M系列,Cortex-M4的频率已经为:180MHz了,基本上与之前的ARM7/9频率差不多了,还有Cortex-M7,频率更高,出现了BGA封装与SDRAM DDR等。看来处理器越来越大众化了,物联网上的电子设备联网,也越来越普及了,硬件成本不断降低是大势所趋,因此,作为一个电子设计人员,还是要不断的学习掌握更多的技术知识与基础,从而不会被社会很快淘汰。

      最近买了一个现成的STM32F429 Discovery 的开发板,想尝试一下较大点的嵌入式操作系统如RTEMS的移植与应用。因为有了STM32F103/107的基础,熟悉了硬件与固件库,STM32F429其实很容易入手。下面就先定时器中断点个LED试下吧,主要是要组织好工程目录。

      我是根据之前一直使用STM32F103的工程目录改了一下,使用STM32F4XX的最新固件库V1.6.1,至于为何不去直接操作寄存器,我想,虽然自己是硬件出身,搞寄存器更深入的了解处理器,但是,毕竟寄存器过多,有了库,可以封装一下,这样更可以快速的上手。如果需要查看寄存器,也是可以查的。用固件库可以少一些错误,毕竟我们是做应用的,首先要学会使用CPU来实现我们要的功能。

       工程目录如下:这里使用最新的Keil MDK V5.17版本的,STM32F4XX的器件库等还需要进一步下载。这里使用的是自带的ST-Link下载程序,当然使用Jlink也是可以的。




        STM32F429的系统定时器,原来是系统时钟180MHz的8分频,这个可以看一下STM32F4XX的参考手册,里面时钟RCC部分的框架介绍。我这里为了定时为1S,因此计算了一下。



以下为Tim2.c的主程序。Tim2.h 只是函数声明。



[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /********************     (C) COPYRIGHT 2016     ************************** 
  2.  * 文件名  :Tim2.c 
  3.  * 描述    :定时器timer2 测试例程        
  4.  * 实验平台:STM32F429ZIT6 
  5.  * 库版本  :V1.6.1 
  6.  * 
  7.  * 编写日期:2016-05-02 
  8.  * 修改日期: 
  9.  * 作者    : 
  10. ****************************************************************************/  
  11. #include "Tim2.h"  
  12.   
  13. /* 
  14.  * 函数名:TIM2_NVIC_Configuration 
  15.  * 描述  :TIM2中断优先级配置 
  16.  * 输入  :无 
  17.  * 输出  :无    
  18.  */  
  19. void TIM2_NVIC_Configuration(void)  
  20. {  
  21.     NVIC_InitTypeDef NVIC_InitStructure;   
  22.       
  23.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);                                                       
  24.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;     
  25.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  
  26.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    
  27.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  28.     NVIC_Init(&NVIC_InitStructure);  
  29. }  
  30.   
  31.   
  32. /*TIM_Period--1000   TIM_Prescaler--(22500-1) -->中断周期为 
  33.   ((1/180000000)*8)*22500*1000=1S    1秒定时器 */  
  34. void TIM2_Configuration(void)  
  35. {  
  36.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  37.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);  
  38.     TIM_DeInit(TIM2);  
  39.     TIM_TimeBaseStructure.TIM_Period=1000;       /* 自动重装载寄存器周期的值(计数值) */  
  40.     /* 累计 TIM_Period个频率后产生一个更新或者中断 */  
  41.     TIM_TimeBaseStructure.TIM_Prescaler= (22500 - 1);   /* 时钟预分频数 (180M/8)/22500 */  
  42.     TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;       /* 采样分频 */  
  43.     TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */  
  44.     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
  45.     TIM_ClearFlag(TIM2, TIM_FLAG_Update);                           /* 清除溢出中断标志 */  
  46.     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  
  47.     TIM_Cmd(TIM2, ENABLE);                                                      /* 开启时钟 */      
  48.     //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE);        /* 先关闭等待使用 */      
  49. }  
  50.   
  51. /* 
  52.  * 函数名:TIM2_Config 
  53.  * 描述  :TIM2配置 
  54.  * 输入  :无 
  55.  * 输出  :无    
  56.  */  
  57. void TIM2_Config(void)  
  58. {  
  59.   TIM2_Configuration();  
  60.     TIM2_NVIC_Configuration();  
  61. }  
  62.   
  63.   
  64. /*******************      (C) COPYRIGHT 2016        *END OF FILE************/  




以下为:led.c的文件。


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /********************       (C) COPYRIGHT 2014  *************************** 
  2.  * 文件名  :led.c 
  3.  * 描述    :led 应用函数库          
  4.  * 实验平台: 
  5.  * 硬件连接:----------------------- 
  6.  *          |   PG14 - LED1(RUN)     |    
  7.  *           -----------------------  
  8.  * 库版本  :ST3.5.0 
  9.  * 编写日期:2014-11-04 
  10.  * 修改日期: 
  11.  * 作者    : 
  12. ****************************************************************************/  
  13. #include "led.h"  
  14.   
  15. /* 
  16.  * 函数名:LED_GPIO_Config 
  17.  * 描述  :配置LED用到的I/O口 
  18.  * 输入  :无 
  19.  * 输出  :无 
  20.  */  
  21. void LED_GPIO_Config(void)  
  22. {         
  23.     /*定义一个GPIO_InitTypeDef类型的结构体*/  
  24.     GPIO_InitTypeDef GPIO_InitStructure;  
  25.   
  26.     /*开启 LED1 的GPIOx的外设时钟*/  
  27.     RCC_AHB1PeriphClockCmd( RCC_LED1, ENABLE);   
  28.     /*选择要控制的LED1 GPIOx引脚*/                                                               
  29.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_LED1;      
  30.     /*设置引脚模式为通用推挽输出*/  
  31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;     
  32.     /*设置引脚速率为50MHz */     
  33.     GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;   
  34.     /* 设置为推挽输出模式 */  
  35.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  36.     /* 设置为上拉 */   
  37.         GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;  
  38.     /*调用库函数,初始化LED1 的GPIOx*/      
  39.     GPIO_Init(GPIO_LED1_PORT, &GPIO_InitStructure);         
  40.   
  41.         /*开启 LED2 的GPIOx的外设时钟*/  
  42.     RCC_AHB1PeriphClockCmd( RCC_LED2, ENABLE);   
  43.     /*选择要控制的LED2 GPIOx引脚*/                                                               
  44.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_LED2;      
  45.     /*设置引脚模式为通用推挽输出*/  
  46.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;     
  47.     /*设置引脚速率为50MHz */     
  48.     GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;   
  49.     /* 设置为推挽输出模式 */  
  50.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  51.     /* 设置为上拉 */   
  52.         GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;  
  53.     /*调用库函数,初始化LED1 的GPIOx*/      
  54.     GPIO_Init(GPIO_LED2_PORT, &GPIO_InitStructure);   
  55.           
  56.     /* 关闭LED1   */  
  57.     //GPIO_ResetBits(GPIO_LED1_PORT, GPIO_Pin_LED1);  
  58.     //GPIO_ResetBits(GPIO_LED2_PORT, GPIO_Pin_LED2);      
  59. }  
  60.   
  61.   
  62.   
  63.   
  64. /******************* (C) COPYRIGHT  2014 *****END OF FILE************/  




以下为LED的引脚定义:led.h


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /********************       (C) COPYRIGHT 2014  *************************** 
  2.  * 文件名  :led.h 
  3.  * 描述    :led 应用函数库          
  4.  * 实验平台: 
  5.  * 硬件连接:----------------------- 
  6.  *          |   PG14 - LED1(RUN)     |    
  7.  *           -----------------------  
  8.  * 库版本  :V1.6.1 
  9.  * 编写日期:2016-04-30 
  10.  * 修改日期: 
  11.  * 作者    : 
  12. ****************************************************************************/  
  13. #ifndef __LED_H  
  14. #define __LED_H  
  15.   
  16. #include "stm32f4xx.h"  
  17.   
  18. /* the macro definition to trigger the led on or off  
  19.  * 1 - off 
  20.  - 0 - on 
  21.  */  
  22. #define ON  1  
  23. #define OFF 0  
  24.   
  25. #define RCC_LED1                        RCC_AHB1Periph_GPIOG  
  26. #define GPIO_LED1_PORT          GPIOG  
  27. #define GPIO_Pin_LED1               GPIO_Pin_13  
  28.   
  29. #define RCC_LED2                        RCC_AHB1Periph_GPIOG  
  30. #define GPIO_LED2_PORT          GPIOG  
  31. #define GPIO_Pin_LED2               GPIO_Pin_14  
  32.   
  33. //带参宏,可以像内联函数一样使用  
  34. #define LED1(a) if (a)  \  
  35.                     GPIO_SetBits(GPIO_LED1_PORT,GPIO_Pin_LED1);\  
  36.                     else        \  
  37.                     GPIO_ResetBits(GPIO_LED1_PORT,GPIO_Pin_LED1)  
  38.   
  39. #define LED2(a) if (a)  \  
  40.                     GPIO_SetBits(GPIO_LED2_PORT,GPIO_Pin_LED2);\  
  41.                     else        \  
  42.                     GPIO_ResetBits(GPIO_LED2_PORT,GPIO_Pin_LED2)  
  43.                       
  44.   
  45. void LED_GPIO_Config(void);  
  46.   
  47. #endif /* __LED_H */  



主程序:硬件的初始化。



[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /********************        (C) COPYRIGHT 2016        ************************** 
  2.  * 文件名  :main.c 
  3.  * 描述    :STM32F429 LED测试     
  4.  * 实验平台: STM32F429ZIT6 
  5.  * 库版本  :V1.6.1 
  6.  * 编写日期:2016-05-02 
  7.  * 修改日期: 
  8.  * 作者    : 
  9. **********************************************************************************/  
  10.   
  11. #include "stm32f4xx.h"  
  12. //#include "usart1.h"  
  13. #include "led.h"  
  14. #include "Tim2.h"  
  15.   
  16. void Delay(__IO uint32_t nTime)  
  17. {   
  18.    
  19.   while(--nTime != 0);  
  20. }  
  21.   
  22.   
  23. /*  
  24.  * 函数名:main 
  25.  * 描述  : "主机"的主函数 
  26.  * 输入  :无 
  27.  * 输出  : 无 
  28.  */  
  29. int main(void)  
  30. {      
  31.     LED_GPIO_Config();  
  32.     TIM2_Config();  
  33.     LED1(ON);  
  34.   LED2(ON);  
  35.     while(1)  
  36.     {   
  37. #if 0  
  38.         Delay(0x2FFFFF);  
  39.         LED1(OFF);  
  40.         LED2(OFF);  
  41.         Delay(0x2FFFFF);          
  42.         LED1(ON);  
  43.         LED2(ON);  
  44. #endif  
  45.     }     
  46. }  
  47. /******************* (C) COPYRIGHT 2014 *****END OF FILE************/  



以下为真正的实现函数:定时器2中断函数 stm32f4xx_it.c



[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.   * @brief  This function handles TIM2 Handler. 
  3.   * @param  None 
  4.   * @retval None 
  5.   */  
  6. void TIM2_IRQHandler(void)  
  7. {  
  8.     if (TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)  
  9.     {     
  10.         TIM_ClearFlag(TIM2, TIM_FLAG_Update);  
  11.         TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);  
  12.         GPIO_WriteBit(GPIO_LED1_PORT,GPIO_Pin_LED1,  
  13.         (BitAction)(1-GPIO_ReadOutputDataBit(GPIO_LED1_PORT,GPIO_Pin_LED1)));  
  14.     }  
  15. }  



      编译并烧写,基本上可以看到LED 1S的亮,1S的灭,然后不断的循环下去,一般用于程序的运行指示灯。

重要的总结:

(1)GPIO的时钟,STM32F103的是APB时钟,STM32F429为:RCC_AHB1PeriphClockCmd,我开始弄错了,程序不运行!!

(2)STM32F429虽然180MHz的主频,但是系统定时器的时钟为其的8分频,STM32F103是直接使用的72MHz的主频,因此在计算分频与周期数时,要使用180MHz/8 的定时器基本时钟去计算。


Keil MDK 5.17的工程下载:

阅读(6301) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~