蘇州移動(dòng)網(wǎng)站建設(shè)網(wǎng)站建站價(jià)格
嵌入式開發(fā)學(xué)習(xí)之STM32F407串口(USART)收發(fā)數(shù)據(jù)(三)
- 開發(fā)涉及工具
- 一、選定所使用的串口
- 二、配置串口
- 1.配置串口的I/O
- 2.配置串口參數(shù)屬性
- 3.配置串口中斷
- 4.串口中斷在哪里處理
- 5.串口如何發(fā)送字符串
- 三、封裝串口配置庫文件
- 1.創(chuàng)建頭文件(.h)文件
- 2.創(chuàng)建源文件(.c)文件
- 四、功能實(shí)現(xiàn)
此次實(shí)現(xiàn)目的:
1.芯片上電啟動(dòng)時(shí)發(fā)送“Hello Word!”
2.發(fā)送給芯片的數(shù)據(jù),芯片又通過串口發(fā)送回來
有工程實(shí)例,鏈接在最底部。
開發(fā)涉及工具
開發(fā)環(huán)境(IDE):IAR-ARM8.32.4
開發(fā)板:STM32_F4VE_V2.0
下載器:J-Link
串口調(diào)試軟件:XCOM_V2.6
固件庫版本:STM32F4xx_DSP_StdPeriph_Lib_V1.8.0
一、選定所使用的串口
1.我使用的開發(fā)板是STM32F407VE芯片,芯片提供有6個(gè)串口。在開發(fā)板上可以看到其單獨(dú)引出了串口針腳,那么我們就需要通過原理圖來確認(rèn)這個(gè)針腳是連接的哪一個(gè)串口,如下圖所示,從原理圖中我們不難看出,收發(fā)引腳是接在芯片的PA9和PA10上面的。
2.我們翻看芯片數(shù)據(jù)手冊(cè)的引腳定義表,可以發(fā)現(xiàn)PA9對(duì)應(yīng)芯片USART1_TX,PA10對(duì)應(yīng)USART1_RX?,F(xiàn)在我們就可以開始配置串口1來達(dá)到數(shù)據(jù)收發(fā)的效果。
3.注意:若我們是自己設(shè)計(jì)電路,則步驟相反。先確認(rèn)要使用的串口編號(hào),然后確認(rèn)串口對(duì)應(yīng)的引腳,最后才將其引出針腳
二、配置串口
我們依舊可以在固件庫里面去找到關(guān)于配置USART的例程,在前面配置GPIO的時(shí)候我有提到過,這里不再贅述,直接上配置代碼
1.配置串口的I/O
這里值得注意的就是要將端口設(shè)置成復(fù)用模式,其他配置相同;
void USART1_IO_Conf(void)
{GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//IO口用作串口引腳要配置復(fù)用模式GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//TX引腳GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//IO口用作串口引腳要配置復(fù)用模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//RX引腳GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);
}
2.配置串口參數(shù)屬性
這里值得注意的還有里面調(diào)用了一個(gè)配置串口中斷的函數(shù)USART1_NVICConf()(解釋一下什么是中斷,中斷就是有一個(gè)事件發(fā)生了,我需要打斷CPU現(xiàn)在的工作,轉(zhuǎn)而來處理現(xiàn)在發(fā)生的事件),用在這里結(jié)合此句USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);的意思是配置的數(shù)據(jù)接收中斷,比如說別的設(shè)備給我發(fā)送了字符,那么CPU你現(xiàn)在啥都別忙干,先來看看這個(gè)字符是什么。
void USART1_Conf(uint32_t baud)//配置函數(shù),定義一個(gè)形參用于配置波特率
{USART_InitTypeDef USART_InitStructure;//定義配置串口的結(jié)構(gòu)體變量RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//開啟串口1的時(shí)鐘USART_DeInit(USART1);//大概意思是解除此串口的其他配置USART_StructInit(&USART_InitStructure);USART_InitStructure.USART_BaudRate = baud;//設(shè)置波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字節(jié)長(zhǎng)度為8bitUSART_InitStructure.USART_StopBits = USART_StopBits_1;//1個(gè)停止位USART_InitStructure.USART_Parity = USART_Parity_No ;//沒有校驗(yàn)位USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//將串口配置為收發(fā)模式USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不提供流控 USART_Init(USART1,&USART_InitStructure);//將相關(guān)參數(shù)初始化給串口1USART1_NVICConf();//配置串口的中斷USART_ClearFlag(USART1,USART_FLAG_RXNE);//初始配置時(shí)清除接受置位USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//初始配置接收中斷USART_Cmd(USART1,ENABLE);//開啟串口1
}
3.配置串口中斷
那要如何配置串口的中斷呢,其方法如下
void USART1_NVICConf(void)
{NVIC_InitTypeDef NVIC_InitStructure;//中斷控制結(jié)構(gòu)體變量定義NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中斷通道指定為USART1NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主優(yōu)先級(jí)為0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//次優(yōu)先級(jí)為1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//確定使能NVIC_Init(&NVIC_InitStructure);//初始化配置此中斷通道
}
4.串口中斷在哪里處理
那么問題來了,我產(chǎn)生了事件,我CPU要在哪里來查看呢,這就需要中斷服務(wù)函數(shù)來實(shí)現(xiàn),中斷服務(wù)函數(shù)不能隨意命名(但對(duì)其原來的名字進(jìn)行重定義也可以),中斷服務(wù)函數(shù)的名稱我們?cè)谥袛嘞蛄勘碇胁檎?#xff0c;我使用的此版固件在stm32f40_41xx.s大概120行的中斷向量表里面找,然后如下編寫
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判斷是不是真的有中斷發(fā)生{USART_SendData(USART1,USART_ReceiveData(USART1));//又將數(shù)據(jù)發(fā)回去USART_ClearITPendingBit(USART1, USART_IT_RXNE); //已經(jīng)處理就清楚標(biāo)志位 }
}
5.串口如何發(fā)送字符串
我們寫一個(gè)通過串口發(fā)送字符串的函數(shù),可如下編寫:
void Usart_SendString(USART_TypeDef* USARTx,uint8_t *data,uint32_t dataLen)
{uint32_t i;for(i = 0;i < dataLen;i ++){USART_SendData(USARTx,data[i]);//發(fā)送數(shù)據(jù)while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);//等待發(fā)送完成}
}
三、封裝串口配置庫文件
由于我們配置串口和使用串口的功能函數(shù)比較多,放在一個(gè)源文件里面比較雜亂,那么我們可以直接將關(guān)于使用串口的文件封裝成庫文件,通過導(dǎo)入頭文件就可使用,方法如下
1.創(chuàng)建頭文件(.h)文件
在IAR新建一個(gè)空白文件,保存為usart.h(如何新建文件和保存文件,我在《嵌入式開發(fā)學(xué)習(xí)之STM32F407芯片IAR環(huán)境搭建空白工程(一)》有提到,不做贅述),然后語法格式如下,
#ifndef _USART_H//.h文件三要素之一
#define _USART_H//.h文件三要素之一#include "stm32f4xx.h"//依據(jù)自身工程情況導(dǎo)入頭文件//外部可調(diào)用函數(shù)的聲明
void USART1_IO_Conf(void);
void USART1_Conf(uint32_t baud);
void Usart_SendString(USART_TypeDef* USARTx,uint8_t *data,uint32_t dataLen);#endif//.h文件三要素之一
2.創(chuàng)建源文件(.c)文件
在IAR新建一個(gè)空白文件,保存為usart.h,然后語法格式如下,
#include "usart.h"void USART1_IO_Conf(void)
{GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//IO口用作串口引腳要配置復(fù)用模式GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//TX引腳GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//IO口用作串口引腳要配置復(fù)用模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//RX引腳GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);
}void USART1_NVICConf(void)
{NVIC_InitTypeDef NVIC_InitStructure;//中斷控制結(jié)構(gòu)體變量定義NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中斷通道指定為USART1NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主優(yōu)先級(jí)為0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//次優(yōu)先級(jí)為1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//確定使能NVIC_Init(&NVIC_InitStructure);//初始化配置此中斷通道
}void USART1_Conf(uint32_t baud)//配置函數(shù),定義一個(gè)形參用于配置波特率
{USART_InitTypeDef USART_InitStructure;//定義配置串口的結(jié)構(gòu)體變量RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//開啟串口1的時(shí)鐘USART_DeInit(USART1);//大概意思是解除此串口的其他配置USART_StructInit(&USART_InitStructure);USART_InitStructure.USART_BaudRate = baud;//設(shè)置波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字節(jié)長(zhǎng)度為8bitUSART_InitStructure.USART_StopBits = USART_StopBits_1;//1個(gè)停止位USART_InitStructure.USART_Parity = USART_Parity_No ;//沒有校驗(yàn)位USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//將串口配置為收發(fā)模式USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不提供流控 USART_Init(USART1,&USART_InitStructure);//將相關(guān)參數(shù)初始化給串口1USART1_NVICConf();//配置串口的中斷USART_ClearFlag(USART1,USART_FLAG_RXNE);//初始配置時(shí)清除接受置位USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//初始配置接受中斷USART_Cmd(USART1,ENABLE);//開啟串口1
}/******** 串口1 中斷服務(wù)函數(shù) ***********/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判斷是不是真的有中斷發(fā)生{USART_SendData(USART1,USART_ReceiveData(USART1));//又將數(shù)據(jù)發(fā)回去USART_ClearITPendingBit(USART1, USART_IT_RXNE); //已經(jīng)處理就清楚標(biāo)志位 }
}void Usart_SendString(USART_TypeDef* USARTx,uint8_t *data,uint32_t dataLen)
{uint32_t i;for(i = 0;i < dataLen;i ++){USART_SendData(USARTx,data[i]);//發(fā)送數(shù)據(jù)while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);//等待發(fā)送完成}
}
四、功能實(shí)現(xiàn)
功能實(shí)現(xiàn)時(shí)我們?cè)谥骱瘮?shù)中調(diào)用配置函數(shù)即可,編寫如下
#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"void main()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//使用了中斷,則這一句必須要有USART1_IO_Conf();//配置串口的IOUSART1_Conf(115200);//串口配置成波特率115200Usart_SendString(USART1,"Hello Word!\r\n",13);//發(fā)送字符串while(1){}
}
實(shí)驗(yàn)結(jié)果:
工程實(shí)例鏈接:https://download.csdn.net/download/qq_45100839/88425993