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

STM32基础设计---时钟中断(控制LED灯)

[复制链接]
STMCU小助手 发布时间:2023-1-4 21:30
本文将介绍STM32的基础时钟,通过时钟中断来控制LED灯的亮灭。

本文的大致思路如下:
1,LED的GPIO口初始化
2,中断初始化
3,时钟初始化
4,编写中断函数
5,编写主函数

首先讲下笔者在做这个设计时得到的教训:

        笔者最初是用TIM6基础时钟来实现设计功能,在编写完代码后发现,灯不亮,于是笔者就开始整问题了。先看看代码有没有编写错误,检查一遍后,中断通道使用正确,TIM6配置正确,LED灯的串口也没有问题,中断函数也正常编写了。然后笔者纠结了,他妈代码全对了怎么就运行失败?(原谅笔者爆粗口,因为当时心情的确很不好,可以想象一下,辛辛苦苦桥的代码,没什么毛病,结果到了板子上还运行不了)之后笔者认认真真核对代码,还是没解决问题,之后没办法了,去论坛上请教大佬去了,(还是大佬厉害)我把问题说了后,大佬看了后说,可能是你的启动文件里没有TIM6中断(笔者顿悟了),他妈我怎么没想到这个。。。之后去检查发现果然没有这个中断函数入口(STM32中必须按照要求写中断函数名才能进入中断),之后笔者发现我的工程中定义的是STM32F10X_MD这个头文件,这个头文件里没有TIM6这个中断名(当初笔者也发现了这个问题,自己看定义了个#define 54(因为我查了其他头文件是54)),又检查了启动文件,发现没有写中断函数入口,笔者就把TIM6换成TIM3(通用定时器)了,之后就正常了。希望可以帮助到和我犯同样错误的人。


下面进入主题,详细解释代码:

1,LED的GPIO口初始化
  1. void led_init()
  2. {
  3.         GPIO_InitTypeDef led_gpio;
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
  5.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);因为GPIOC13口的13引脚被重映射了,所以需要先关闭重映射
  6.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
  7.         led_gpio.GPIO_Pin = GPIO_Pin_13;
  8.         led_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  9.         led_gpio.GPIO_Speed = GPIO_Speed_50MHz;
  10.         GPIO_Init(GPIOC,&led_gpio);
  11. }
复制代码

2,中断初始化
  1. void nvic_init()
  2. {
  3.         NVIC_InitTypeDef nvic;
  4.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);定义分组
  5.         nvic.NVIC_IRQChannel  =TIM3_IRQn;中断通道名
  6.         nvic.NVIC_IRQChannelPreemptionPriority = 1;
  7.         nvic.NVIC_IRQChannelSubPriority = 0;
  8.         nvic.NVIC_IRQChannelCmd= ENABLE;中断时能
  9.         NVIC_Init(&nvic);初始化寄存器
  10. }
复制代码


3,时钟初始化
  1. void tim_init()
  2. {
  3.         TIM_TimeBaseInitTypeDef tim;定义时钟结构体
  4.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);时能TIM3
  5.         tim.TIM_Period = 1000-1;计数周期
  6.         tim.TIM_Prescaler = 72 - 1;预分频数
  7.         tim.TIM_ClockDivision = TIM_CKD_DIV1;时钟分频,设置定时器时钟CK_INT频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能
  8.         tim.TIM_CounterMode = TIM_CounterMode_Up;定时器基础方式,可以是向上计数、向下计数、中心对其模式。基本定时器只能是向上计数。
  9.         tim.TIM_RepetitionCounter = 0;重复计数器,属于高级控制寄存器专用寄存器位,这里不用设置。
  10.        
  11.         TIM_TimeBaseInit(TIM3,&tim);初始化
  12.         TIM_ClearFlag(TIM3,TIM_FLAG_Update);清除中断标志
  13.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);开启中断
  14.         TIM_Cmd(TIM3,ENABLE);TIM3使能
  15.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,DISABLE);关闭TIM3时钟,等需要时在打开
  16. }
复制代码


4,编写中断服务函数
  1. void TIM3_IRQHandler()
  2. {
  3.        
  4.         if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET){判断是否可以中断
  5.                 //PrintString("\r\ntime inter");这个是笔者在调试程序时用的串口
  6.                 time++;
  7.                 if(time >=1000)实现1秒一计数
  8.                 {
  9.                         //PrintString("\r\nin time inter");
  10.                        
  11.                         time = 0;以下是实现灯的亮灭
  12.                         if(GPIOC->ODR & GPIO_Pin_13)
  13.                         {
  14.                                 GPIOC->BRR = GPIO_Pin_13;
  15.                         }else
  16.                         {
  17.                                 GPIOC->BSRR = GPIO_Pin_13;
  18.                         }
  19.                 }
  20.         }
  21.         TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);清除中断标志位避免重复进入中断
  22. }
复制代码


5,主函数
  1. int main()
  2. {
  3.         led_init();LED初始化
  4.         tim_init();时钟初始化
  5.         nvic_init();中断初始化
  6.         //nvic_usart_init();
  7.         //usart_init();
  8.         GPIOC->BSRR = GPIO_Pin_13;预先打开灯
  9.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);使能TIM3
  10.         delay(1000);延时1秒
  11.         while(1){死循环
  12.                 //PrintString("\r\nÑ­»·");
  13.         }
  14. }
复制代码


下面粘贴详细代码:

注:注释掉的部分是笔者用串口在调试程序,可忽略(笔者经验有限,如有不妥之处请指教)

  1. #include<stm32f10x.h>
  2. static unsigned int time;
  3. uint8_t TxCount=0;
  4. uint8_t Count=0;
  5. static uint8_t TxBuff[256];
  6. void delay(uint16_t n)
  7. {
  8.         int i,j;
  9.         for(i=0;i<n;i++)
  10.                 for(j=0;j<8500;j++);
  11. }
  12. void tim_init()
  13. {
  14.         TIM_TimeBaseInitTypeDef tim;
  15.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  16.         tim.TIM_Period = 1000-1;
  17.         tim.TIM_Prescaler = 71;
  18.         tim.TIM_ClockDivision = TIM_CKD_DIV1;
  19.         tim.TIM_CounterMode = TIM_CounterMode_Up;
  20.         tim.TIM_RepetitionCounter = 0;
  21.        
  22.         TIM_TimeBaseInit(TIM3,&tim);
  23.         TIM_ClearFlag(TIM3,TIM_FLAG_Update);
  24.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
  25.         TIM_Cmd(TIM3,ENABLE);
  26.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,DISABLE);
  27. }
  28. void PrintU8(uint8_t data)
  29. {
  30.         TxBuff[TxCount++]=data;
  31.         if(!(USART1->CR1 & USART_CR1_TXEIE))
  32.         {
  33.                 USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
  34.         }
  35. }

  36. void PrintString(uint8_t *s)
  37. {
  38.         uint8_t *p;
  39.         p=s;
  40.         while(*p != '\0')
  41.         {
  42.                 PrintU8(*p);
  43.                 p++;
  44.         }
  45. }
  46. void usart_init()
  47. {
  48.          GPIO_InitTypeDef Uart_A;  
  49.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  50.        
  51.                 Uart_A.GPIO_Pin = GPIO_Pin_9;  
  52.     Uart_A.GPIO_Speed = GPIO_Speed_50MHz;  
  53.     Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;  
  54.     GPIO_Init(GPIOA,&Uart_A);  
  55.       
  56.     Uart_A.GPIO_Pin = GPIO_Pin_10;  
  57.     Uart_A.GPIO_Speed = GPIO_Speed_50MHz;  
  58.     Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110  
  59.     GPIO_Init(GPIOA,&Uart_A);  
  60.        
  61.         USART_InitTypeDef Uart;  
  62.       
  63.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  
  64.     Uart.USART_BaudRate = 115200;  
  65.     Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  66.     Uart.USART_Mode = USART_Mode_Tx;  
  67.     Uart.USART_Parity = USART_Parity_No;  
  68.     Uart.USART_StopBits = USART_StopBits_1;  
  69.     Uart.USART_WordLength = USART_WordLength_8b;  
  70.     USART_Init(USART1,&Uart);  
  71.       
  72.     USART_Cmd(USART1,ENABLE);  
  73.     USART_ClearFlag(USART1,USART_FLAG_TC);
  74. }
  75. void nvic_usart_init()
  76. {
  77.                 NVIC_InitTypeDef nvic;  
  78.       
  79.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
  80.       
  81.     nvic.NVIC_IRQChannelPreemptionPriority = 0;  
  82.     nvic.NVIC_IRQChannelSubPriority = 0;  
  83.     nvic.NVIC_IRQChannel = USART1_IRQn;  
  84.     nvic.NVIC_IRQChannelCmd = ENABLE;  
  85.     NVIC_Init(&nvic);  
  86. }
  87. void nvic_init()
  88. {
  89.         NVIC_InitTypeDef nvic;
  90.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  91.         nvic.NVIC_IRQChannel  =TIM3_IRQn;
  92.         nvic.NVIC_IRQChannelPreemptionPriority = 1;
  93.         nvic.NVIC_IRQChannelSubPriority = 0;
  94.         nvic.NVIC_IRQChannelCmd= ENABLE;
  95.         NVIC_Init(&nvic);
  96. }
  97. void led_init()
  98. {
  99.         GPIO_InitTypeDef led_gpio;
  100.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
  101.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
  102.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
  103.         led_gpio.GPIO_Pin = GPIO_Pin_13;
  104.         led_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  105.         led_gpio.GPIO_Speed = GPIO_Speed_50MHz;
  106.         GPIO_Init(GPIOC,&led_gpio);
  107. }
  108. int main()
  109. {
  110.         led_init();
  111.         tim_init();
  112.         nvic_init();
  113.         //nvic_usart_init();
  114.         //usart_init();
  115.         GPIOC->BSRR = GPIO_Pin_13;
  116.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  117.         delay(1000);
  118.         while(1){
  119.                 //PrintString("\r\nÑ­»·");
  120.         }
  121. }
  122. void TIM3_IRQHandler()
  123. {
  124.        
  125.         if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET){
  126.                 //PrintString("\r\ntime inter");
  127.                 time++;
  128.                 if(time >=1000)
  129.                 {
  130.                         //PrintString("\r\nin time inter");
  131.                        
  132.                         time = 0;
  133.                         if(GPIOC->ODR & GPIO_Pin_13)
  134.                         {
  135.                                 GPIOC->BRR = GPIO_Pin_13;
  136.                         }else
  137.                         {
  138.                                 GPIOC->BSRR = GPIO_Pin_13;
  139.                         }
  140.                 }
  141.         }
  142.         TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);
  143. }
  144. void USART1_IRQHandler(void)
  145. {
  146.          if(USART1->SR & USART_SR_TC)
  147.     {  
  148.         USART1->DR = TxBuff[Count++];
  149.         if(TxCount == Count)
  150.         {  
  151.             USART1->CR1 &= ~USART_CR1_TXEIE;  
  152.         }  
  153.     }  
  154. }
复制代码

————————————————
版权声明:家安



收藏 评论0 发布时间:2023-1-4 21:30

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版