m_<:整個(gè)程序除去基本配置外由四部分組成,main.c、bsp_usart.c、bsp_led.c和stm32f4xx_it.c。其中,bsp_usart.c及.h負(fù)責(zé)外設(shè)USART寄存器的配置,使其能正常工作。bsp_led.c及.h負(fù)責(zé)外設(shè)LED寄存器的配置,使其能正常工作,main.c則是在USART配置完能正常操作后來實(shí)現(xiàn)USART怎么接收數(shù)據(jù),然后通過控制LED的顏色判斷接收到什么數(shù)據(jù)。在stm32f4xx_it.c中寫入中斷服務(wù)函數(shù),這是本節(jié)重點(diǎn)。
1 main.c
#include "stm32f4xx.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h" //可將全局變量引入
int main(void)
{
LED_GPIO_Config(); //配置GPIO口
USART_Config(); //配置USART
while (1)
{
if(Flag=='a') //Flag為全局變量,F(xiàn)lag為我們輸入的字符(后面進(jìn)一步說明)
{
Flag == '0'; //Flag復(fù)位
GPIO_ResetBits(GPIOF, GPIO_Pin_6); //若輸入為'a',則紅燈亮
}
if(Flag=='b')
{
Flag == '0';
GPIO_ResetBits(GPIOF, GPIO_Pin_7); //若輸入為'b',則綠燈亮
}
}
}
2.1 bsp_led.h
#ifndef _BSP_LED_H //防止重定義
#define _BSP_LED_H
#include "stm32f4xx.h"
void LED_GPIO_Config(void); //聲明配置函數(shù)
#endif
2.2 bsp_led.c
//bsp: board support package(板級(jí)支持包)
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
//以下四個(gè)步驟適合所有外設(shè)的初始化
/* 第一步:開GPIO的時(shí)鐘 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //GPIOF在AHB1總線上,另外注意,系統(tǒng)時(shí)鐘已經(jīng)自己設(shè)定了
/* 第二步:定義一個(gè)GPIO初始化結(jié)構(gòu)體 */
GPIO_InitTypeDef GPIO_InitStruct;
/* 第三步:配置GPIO初始化結(jié)構(gòu)體的成員 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; //Pin6紅色、Pin7綠色、Pin8藍(lán)色
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //輸出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽輸出
GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed; //2MHz
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉電阻
/* 第四步:調(diào)用GPIO初始化函數(shù),把配置好的結(jié)構(gòu)體的成員的參數(shù)寫入寄存器 */
GPIO_Init(GPIOF, &GPIO_InitStruct); //將上述參數(shù)賦給GPIOF
GPIO_SetBits(GPIOF,GPIO_Pin_6); //輸出置1,紅燈滅
/* 配置綠燈GPIO引腳 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7; //Pin7綠色
GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_SetBits(GPIOF,GPIO_Pin_6); //輸出置1,綠燈滅
}
3.1 bsp_usart.h
#ifndef __BSP_USART_H
#define __BSP_USART_H
#include "stm32f4xx.h"
extern char Flag; //聲明全局變量Flag
void USART_Config(void); //配置USART
#endif
3.2 bsp_usart.c
#include "./usart/bsp_usart.h"
char Flag = '0'; //定義變量Flag,在頭文件中聲明為全局變量
/***************** 配置USART發(fā)送數(shù)據(jù)中斷 **********************/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //定義一個(gè)中斷結(jié)構(gòu)體
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //選擇嵌套向量中斷控制器組
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //設(shè)置USART為中斷源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //搶斷優(yōu)先級(jí)為1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子優(yōu)先級(jí)為1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC
}
void USART_Config(void)
{
/* 第一步:初始化GPIO */
GPIO_InitTypeDef GPIO_InitStructure; //TX與PA9相連,RX與PA10相連
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOA, ENABLE); //使能GPIO時(shí)鐘
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置Tx引腳為復(fù)用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //選擇復(fù)用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //選擇復(fù)用的發(fā)送引腳
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //選擇復(fù)用的接收引腳
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //將PA9復(fù)用到USART1的TX上
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //將PA10復(fù)用到USART1的RX上
/* 第二步:配置串口初始化結(jié)構(gòu)體 */
USART_InitTypeDef USART_InitStructure; //定義一個(gè)USART結(jié)構(gòu)體
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART時(shí)鐘
/* 配置串口USART1模式 */
USART_InitStructure.USART_BaudRate = 115200; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位字長(zhǎng)
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無校驗(yàn)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //無硬件流
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //選擇輸入和輸出模式
USART_Init(USART1, &USART_InitStructure); //初始化USART
/* 第三步:配置串口的接收中斷 */
NVIC_Configuration(); //嵌套向量中斷控制器NVIC配置
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能串口接收中斷,中斷一直打開,接收到一個(gè)字節(jié)后,判斷RXNE位為1,執(zhí)行其中的中斷服務(wù)函數(shù)
/* 第四步:使能串口 */
USART_Cmd(USART1, ENABLE);
}
4 stm32f4xx_it.c
#include "stm32f4xx_it.h"
#include "./usart/bsp_usart.h" //可將全局變量引入
void USART1_IRQHandler(void)
{
uint8_t ucTemp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判斷TDR是否為非空,收到數(shù)據(jù)TXE位置1
{
ucTemp = USART_ReceiveData(USART1); //將字符轉(zhuǎn)移到ucTemp中
USART_SendData(USART1, ucTemp); //將收到的字符發(fā)送出去
Flag = ucTemp; //將收到的字符轉(zhuǎn)移到Flag中
}
}
說明1:我們需要一個(gè)變量Flag在中斷服務(wù)函數(shù)與主函數(shù)之間傳遞信息,因?yàn)槭莾蓚€(gè)不同的.c,故需要Flag為全局變量,定義方法:
1、在一個(gè).c文件里面定義,可賦值
2、然后在該頭文件里面用extern關(guān)鍵字申明
3、其他.c文件要使用的時(shí),包含該頭文件就可以了
4、頭文件里面不能給變量賦值
說明2:對(duì)于發(fā)送數(shù)據(jù),發(fā)送出去了再判斷TDR是否為空;對(duì)于接收數(shù)據(jù),接收之前先對(duì)RDR判斷是否為不空。兩者區(qū)別要注意。
說明3:本節(jié)只打開了數(shù)據(jù)接收中斷,當(dāng)判斷有數(shù)據(jù)進(jìn)來即刻執(zhí)行中斷服務(wù)函數(shù),若是服務(wù)函數(shù)較大,可通過Flag傳遞信息,將執(zhí)行任務(wù)分配到主函數(shù)中執(zhí)行。下節(jié)將會(huì)分析另一種接口協(xié)議,CAN口。