由于是第一次使用,记录一下比较好

主要包括的文件有:

STM32F429用USART中断控制LED_#include

由于就写了一个USART中断,东西还是比较简单的

首先bsd_led.c及.h文件都是移植zhi'直接用的,直接贴代码

bsd_led.c

/**
   ******************************************************************************
   * @file    bsp_led.c
   * @author  fire
   * @version V1.0
   * @date    2015-xx-xx
   * @brief   led应用函数接口
   ******************************************************************************
   * @attention
   *
   * 实验平台:秉火  STM32 F429 开发板  
   * 论坛    :http://www.firebbs.cn
   * 淘宝    :https://fire-stm32.taobao.com
   *
   ******************************************************************************
   */
   
 #include "./led/bsp_led.h"    /**
   * @brief  初始化控制LED的IO
   * @param  无
   * @retval 无
   */
 void LED_GPIO_Config(void)
 {        
         /*定义一个GPIO_InitTypeDef类型的结构体*/
         GPIO_InitTypeDef GPIO_InitStructure;        /*开启LED相关的GPIO外设时钟*/
         RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK|
                                LED2_GPIO_CLK|
                                LED3_GPIO_CLK, ENABLE);         /*选择要控制的GPIO引脚*/                                                               
         GPIO_InitStructure.GPIO_Pin = LED1_PIN;            /*设置引脚模式为输出模式*/
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   
     
     /*设置引脚的输出类型为推挽输出*/
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     
     /*设置引脚为上拉模式*/
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        /*设置引脚速率为2MHz */   
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;         /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
         GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);    
     
     /*选择要控制的GPIO引脚*/                                                               
         GPIO_InitStructure.GPIO_Pin = LED2_PIN;    
     GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);    
     
     /*选择要控制的GPIO引脚*/                                                               
         GPIO_InitStructure.GPIO_Pin = LED3_PIN;    
     GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);    
         
         /*关闭RGB灯*/
         LED_RGBOFF;        
 }
 /*********************************************END OF FILE**********************/

bsd_led.h

#ifndef __LED_H
 #define    __LED_H#include "stm32f4xx.h"
//引脚定义
 /*******************************************************/
 //R 红色灯
 #define LED1_PIN                  GPIO_Pin_10                 
 #define LED1_GPIO_PORT            GPIOH                      
 #define LED1_GPIO_CLK             RCC_AHB1Periph_GPIOH//G 绿色灯
 #define LED2_PIN                  GPIO_Pin_11                 
 #define LED2_GPIO_PORT            GPIOH                      
 #define LED2_GPIO_CLK             RCC_AHB1Periph_GPIOH//B 蓝色灯
 #define LED3_PIN                  GPIO_Pin_12                 
 #define LED3_GPIO_PORT            GPIOH                       
 #define LED3_GPIO_CLK             RCC_AHB1Periph_GPIOH
 /************************************************************/ /** 控制LED灯亮灭的宏,
     * LED低电平亮,设置ON=0,OFF=1
     * 若LED高电平亮,把宏设置成ON=1 ,OFF=0 即可
     */
 #define ON  0
 #define OFF 1/* 带参宏,可以像内联函数一样使用 */
 #define LED1(a)    if (a)    \
                     GPIO_SetBits(LED1_GPIO_PORT,LED1_PIN);\
                     else        \
                     GPIO_ResetBits(LED1_GPIO_PORT,LED1_PIN)#define LED2(a)    if (a)    \
                     GPIO_SetBits(LED2_GPIO_PORT,LED2_PIN);\
                     else        \
                     GPIO_ResetBits(LED2_GPIO_PORT,LED2_PIN)#define LED3(a)    if (a)    \
                     GPIO_SetBits(LED3_GPIO_PORT,LED3_PIN);\
                     else        \
                     GPIO_ResetBits(LED3_GPIO_PORT,LED3_PIN) /* 直接操作寄存器的方法控制IO */
 #define    digitalHi(p,i)             {p->BSRRL=i;}        //设置为高电平
 #define digitalLo(p,i)             {p->BSRRH=i;}        //输出低电平
 #define digitalToggle(p,i)     {p->ODR ^=i;}        //输出反转状态/* 定义控制IO的宏 */
 #define LED1_TOGGLE        digitalToggle(LED1_GPIO_PORT,LED1_PIN)
 #define LED1_OFF            digitalHi(LED1_GPIO_PORT,LED1_PIN)
 #define LED1_ON                digitalLo(LED1_GPIO_PORT,LED1_PIN)#define LED2_TOGGLE        digitalToggle(LED2_GPIO_PORT,LED2_PIN)
 #define LED2_OFF            digitalHi(LED2_GPIO_PORT,LED2_PIN)
 #define LED2_ON                digitalLo(LED2_GPIO_PORT,LED2_PIN)#define LED3_TOGGLE        digitalToggle(LED3_GPIO_PORT,LED3_PIN)
 #define LED3_OFF            digitalHi(LED3_GPIO_PORT,LED3_PIN)
 #define LED3_ON                digitalLo(LED3_GPIO_PORT,LED3_PIN)/* 基本混色,后面高级用法使用PWM可混出全彩颜色,且效果更好 */
//红
 #define LED_RED  \
                     LED1_ON;\
                     LED2_OFF;\
                     LED3_OFF//绿
 #define LED_GREEN        \
                     LED1_OFF;\
                     LED2_ON;\
                     LED3_OFF//蓝
 #define LED_BLUE    \
                     LED1_OFF;\
                     LED2_OFF;\
                     LED3_ON                    
 //黄(红+绿)                    
 #define LED_YELLOW    \
                     LED1_ON;\
                     LED2_ON;\
                     LED3_OFF
 //紫(红+蓝)
 #define LED_PURPLE    \
                     LED1_ON;\
                     LED2_OFF;\
                     LED3_ON//青(绿+蓝)
 #define LED_CYAN \
                     LED1_OFF;\
                     LED2_ON;\
                     LED3_ON
                     
 //白(红+绿+蓝)
 #define LED_WHITE    \
                     LED1_ON;\
                     LED2_ON;\
                     LED3_ON
                     
 //黑(全部关闭)
 #define LED_RGBOFF    \
                     LED1_OFF;\
                     LED2_OFF;\
                     LED3_OFF         void LED_GPIO_Config(void);
#endif /* __LED_H */

接下来是pei'配置USART以及NVIC,USART中断

在bsp_usart.h中写好宏定义,其实这样写的目的就是为了方便移植,需要注意的是为了能够使用改进的printf以及canf函数(在相应的.c文件中写了个重定向),这里的头文件包含了stdio,h。

def __USART_H
 #define    __USART_H#include "stm32f4xx.h"
 #include <stdio.h> //引脚定义
 /*******************************************************/
 #define USARTx                             USART1/* 不同的串口挂载的总线不一样,时钟使能函数也不一样,移植时要注意 
  * 串口1和6是      RCC_APB2PeriphClockCmd
  * 串口2/3/4/5/7是 RCC_APB1PeriphClockCmd
  */
 #define USARTx_CLK                         RCC_APB2Periph_USART1
 #define USARTx_CLOCKCMD                    RCC_APB2PeriphClockCmd
 #define USARTx_BAUDRATE                    115200  //串口波特率#define USARTx_RX_GPIO_PORT                GPIOA
 #define USARTx_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOA
 #define USARTx_RX_PIN                      GPIO_Pin_10
 #define USARTx_RX_AF                       GPIO_AF_USART1
 #define USARTx_RX_SOURCE                   GPIO_PinSource10#define USARTx_TX_GPIO_PORT                GPIOA
 #define USARTx_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOA
 #define USARTx_TX_PIN                      GPIO_Pin_9
 #define USARTx_TX_AF                       GPIO_AF_USART1
 #define USARTx_TX_SOURCE                   GPIO_PinSource9/************************************************************/
void USARTx_Config(void);
 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
 void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
 static void NVIC_Configuration(void);#endif /* __USART_H */


 

接下来我们开始配置,在bsp_usart.c文件中:

/**
   ******************************************************************************
   * @file    bsp_usart.c
   * @author  fire
   * @version V1.0
   * @date    2015-xx-xx
   * @brief   重定向c库printf函数到usart端口
   ******************************************************************************
   * @attention
   *
   * 实验平台:秉火  STM32 F429 开发板  
   * 论坛    :http://www.firebbs.cn
   * 淘宝    :https://fire-stm32.taobao.com
   *
   ******************************************************************************
   */ 
   
 #include "./usart/bsp_usart.h"//中断版本,用来控制LED
 //配置NVIC
 static void NVIC_Configuration(void)
 {
   NVIC_InitTypeDef NVIC_InitStructure;
   
   /* 嵌套向量中断控制器组选择 */
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   
   /* 配置USART为中断源 */
   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
   /* 抢断优先级为1 */
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   /* 子优先级为1 */
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   /* 使能中断 */
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   /* 初始化配置NVIC */
   NVIC_Init(&NVIC_InitStructure);
     
     
 } //配置USART
  /**
   * @brief  USART GPIO 配置,工作模式配置。115200 8-N-1 
   * @param  无
   * @retval 无
   */
 void USARTx_Config(void)
 {
   GPIO_InitTypeDef GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;
         
   RCC_AHB1PeriphClockCmd(USARTx_RX_GPIO_CLK|USARTx_TX_GPIO_CLK,ENABLE);  /* 使能 USART 时钟 */
   USARTx_CLOCKCMD(USARTx_CLK, ENABLE);
   
   /* GPIO初始化 */
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   
   /* 配置Tx引脚为复用功能  */
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStructure.GPIO_Pin =  USARTx_TX_PIN  ;  
   GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStructure);  /* 配置Rx引脚为复用功能 */
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStructure.GPIO_Pin =  USARTx_RX_PIN;
   GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStructure);
   
  /* 连接 PXx 到 USARTx_Tx*/
   GPIO_PinAFConfig(USARTx_RX_GPIO_PORT,USARTx_RX_SOURCE,USARTx_RX_AF);  /*  连接 PXx 到 USARTx__Rx*/
   GPIO_PinAFConfig(USARTx_TX_GPIO_PORT,USARTx_TX_SOURCE,USARTx_TX_AF);
   
     
     //下面的都是配置USART的
     
   /* 配置串DEBUG_USART 模式 */
   /* 波特率设置:DEBUG_USART_BAUDRATE */
   USART_InitStructure.USART_BaudRate = USARTx_BAUDRATE;
   /* 字长(数据位+校验位):8 */
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;    
   /* 停止位:1个停止位 */
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   /* 校验位选择:偶校验 */  
     USART_InitStructure.USART_Parity = USART_Parity_No;
   /* 硬件流控制:不使用硬件流 */
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   /* USART模式控制:同时使能接收和发送 */
   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
   /* 完成USART初始化配置 */
   USART_Init(USARTx, &USART_InitStructure); 
     
  /* 嵌套向量中断控制器NVIC配置 */
     NVIC_Configuration();
     
         /* 使能串口接收中断 */
     USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
     
   /* 使能串口 */
   USART_Cmd(USARTx, ENABLE);
 }///重定向c库函数printf到串口,重定向后可使用printf函数
 int fputc(int ch, FILE *f)
 {
         /* 发送一个字节数据到串口 */
         USART_SendData(USARTx, (uint8_t) ch);
         
         /* 等待发送完毕 */
         while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);        
     
         return (ch);
 }///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
 int fgetc(FILE *f)
 {
         /* 等待串口输入数据 */
         while (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);        return (int)USART_ReceiveData(USARTx);
 } /*****************  发送一个字符 **********************/
 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
 {
     /* 发送一个字节数据到USART */
     USART_SendData(pUSARTx,ch);
         
     /* 等待发送数据寄存器为空 */
     while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);    
 }/*****************  发送字符串 **********************/
 void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
 {
     unsigned int k=0;
   do 
   {
       Usart_SendByte( pUSARTx, *(str + k) );
       k++;
   } while(*(str + k)!='\0');
   
   /* 等待发送完成 */
   while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
   {}
 }/*********************************************END OF FILE**********************/

接着,在stm32f4xx_it.c文件中,写一个USART的中断函数,需要注意的是USART1_IRQHandler这个名字很重要,要从.s的启动文件中去寻找USART1的中断名字,你用了什么就要去.s的中断向量表去查,然后写在这里!因为该中断里面需要执行相关的任务,那么我就把需要用到函数的头文件加在最前面,        

ch = USART_ReceiveData( USARTx ); //ch=getchar();这两句话是一个意思,第一个是库函数,第二个是把getchar改在过后的函数(改造的方法请看)bsp_usart.c文件。在写USART中断的时候,主要也就是需要判断个中断标志位,这里主要用到两个中断标志位,一个是USART_GetITStatus,一个是上面的USART_GetFlagStatus,都是set=1的时候表示开始要执行任务咯的意思!

下面中断函数里面的任务想怎么写就怎么写。

    

//Usart_SendString(USARTx,"你爸爸我王继的USART中断程序\n");
            printf("请输入数字1-8\n");

上面的这两句其实也是一个意思,printf类似与getchar去理解,也是重定向了,第一句已经在bsp_usart.c谢过了,直接调用即可

 

#nclude "stm32f4xx_it.h"
 #include "./led/bsp_led.h" 
 #include "./usart/bsp_usart.h" 
void USART1_IRQHandler(void)
 {
     char ch;
     if(USART_GetITStatus(USARTx,USART_IT_RXNE)!=RESET)
         {
 //            ch = USART_ReceiveData( USARTx  );
 //            USART_SendData(USARTx ,ch);       
             /* 获取字符指令 */
     
         ch = USART_ReceiveData( USARTx );
         //ch=getchar();
     printf("接收到字符:%c\n",ch);
     
     /* 根据字符指令控制RGB彩灯颜色 */
     switch(ch)
     {
       case '1':
         LED_RED;       printf("red");
       break;
       case '2':
         LED_GREEN;
       break;
       case '3':
         LED_BLUE;
       break;
       case '4':
         LED_YELLOW;
       break;
       case '5':
         LED_PURPLE;
       break;
       case '6':
         LED_CYAN;
       break;
       case '7':
         LED_WHITE;
       break;
       case '8':
         LED_RGBOFF;
       break;
       default:
         /* 如果不是指定指令字符,打印提示信息 */
         //Show_Message();
                     //Usart_SendString(USARTx,"你爸爸我王继的USART中断程序\n");
                     printf("请输入数字1-8\n");
         break;              
         }
 }
 }

最后的main函数就写的hen很简单了

注意,一定要把初始化的东西先初始化!

#include "stm32f4xx.h"
 #include "./led/bsp_led.h" 
 #include "./usart/bsp_usart.h"  static void Show_Message(void);
   
 /**
   * @brief  主函数
   * @param  无
   * @retval 无
   */
 int main(void)
 {      
   /* 初始化RGB彩灯 */
   LED_GPIO_Config();
     
       /* 初始化USART 配置模式为 115200 8-N-1 */
   USARTx_Config();
     
     
     
       /* 打印指令输入提示信息 */
   Show_Message();    Usart_SendString( USARTx,"这是一个串口中断接收回显实验\n");
   //printf("你爸爸我王继的USART中断程序\n");
 }/**
   * @brief  打印指令输入提示信息
   * @param  无
   * @retval 无
   */
 static void Show_Message(void)
 {
   printf("\r\n   这是一个通过串口通信指令控制RGB彩灯实验 \n");
   printf("使用  USART1  参数为:%d 8-N-1 \n",USARTx_BAUDRATE);
   printf("开发板接到指令后控制RGB彩灯颜色,指令对应如下:\n");
   printf("   指令   ------ 彩灯颜色 \n");
   printf("     1    ------    红 \n");
   printf("     2    ------    绿 \n");
   printf("     3    ------    蓝 \n");
   printf("     4    ------    黄 \n");
   printf("     5    ------    紫 \n");
   printf("     6    ------    青 \n");
   printf("     7    ------    白 \n");
   printf("     8    ------    灭 \n");  
 }