vc++ cserialport 打开多个串口_STM32之USART串口
1. 簡介
串口全稱:Universal synchronous asynchronous receiver transmitter,中文名稱:通用同步異步串行接收發(fā)送器。串口可用于接收和發(fā)送數(shù)據(jù),可以用作跟其他設(shè)備通訊,如藍(lán)牙模塊、GSM模塊、GPS模塊等。
串口中最常見的是RS-232,共有9根線用于通訊,但常用的僅3根線:RXD、TXD、GND。其中RXD用于接收,TXD用于發(fā)送,GND為信號地線,兩個(gè)通訊設(shè)備之間的收發(fā)信號(RXD與TXD)應(yīng)交叉相連。
2. 基本概念
- 波特率:串口異步通訊中由于沒有時(shí)鐘信號,所以兩個(gè)通訊設(shè)備之間需要約定好波特率,即每個(gè)碼元的長度,以便對信號進(jìn)行解碼,常見的波特率為4800、9600、115200 等。波特率越高傳輸速度越快,但出錯(cuò)的概率要更大。
- 通訊的起始和停止信號:串口通訊的一個(gè)數(shù)據(jù)包從起始信號開始,直到停止信號結(jié)束。數(shù)據(jù)包的起始信號由一個(gè)邏輯 0 的數(shù)據(jù)位表示,而數(shù)據(jù)包的停止信號可由 0.5、1、1.5或 2個(gè)邏輯 1的數(shù)據(jù)位表示,只要雙方約定一致即可。
- 有效數(shù)據(jù):在數(shù)據(jù)包的起始位之后緊接著的就是要傳輸?shù)闹黧w數(shù)據(jù)內(nèi)容,也稱為有效數(shù)據(jù),有效數(shù)據(jù)的長度常被約定為 5、6、7或 8位長。
- 數(shù)據(jù)校驗(yàn):在有效數(shù)據(jù)之后,有一個(gè)可選的數(shù)據(jù)校驗(yàn)位。由于數(shù)據(jù)通信相對更容易受到外部干擾導(dǎo)致傳輸數(shù)據(jù)出現(xiàn)偏差,可以在傳輸過程加上校驗(yàn)位來解決這個(gè)問題。校驗(yàn)方法有奇校驗(yàn)(odd)、偶校驗(yàn)(even)、0校驗(yàn)(space)、1校驗(yàn)(mark)以及無校驗(yàn)(noparity)。奇校驗(yàn)要求有效數(shù)據(jù)和校驗(yàn)位中“1”的個(gè)數(shù)為奇數(shù),偶校驗(yàn)與奇校驗(yàn)要求剛好相反,要求幀數(shù)據(jù)和校驗(yàn)位中“1”的個(gè)數(shù)為偶數(shù),0校驗(yàn)是不管有效數(shù)據(jù)中的內(nèi)容是什么,校驗(yàn)位總為“0”,1校驗(yàn)是校驗(yàn)位總為“1”。
- 常用的設(shè)置:波特率9600,8位數(shù)據(jù)位,1位停止位,無校驗(yàn)位,無硬件流控。
串口USART分為兩部分,初始化和處理。
1. 初始化分三步:GPIO、通用中斷、USART。
1.1. GPIO:時(shí)鐘、引腳、輸入輸出模式、端口初始化
- 時(shí)鐘:需要同時(shí)使能GPIO時(shí)鐘
- 引腳:需要選擇指定的引腳
- 輸入輸出模式:TX引腳選擇復(fù)用推挽模式,RX引腳選擇浮空輸入模式
- 端口初始化:初始化指定的端口
1.2. 通用中斷:優(yōu)先級分組、中斷源、優(yōu)先級、使能
- 優(yōu)先級分組:設(shè)定合適的優(yōu)先級分組
- 中斷源:選擇指定的中斷源:USART1_IRQn
- 優(yōu)先級:設(shè)定合適的優(yōu)先級
- 使能:調(diào)用庫函數(shù)即可,可選擇使能多個(gè)中斷,一般情況下只使能接收中斷。
1.3. USART:時(shí)鐘、波特率、數(shù)據(jù)字長、停止位、校驗(yàn)位、硬件流控制、工作模式、初始化、使能。
結(jié)構(gòu)體
typedef struct { uint32_t USART_BaudRate; uint16_t USART_WordLength; uint16_t USART_StopBits; uint16_t USART_Parity; uint16_t USART_Mode; uint16_t USART_HardwareFlowControl; } USART_InitTypeDef;- 時(shí)鐘:需要使能USART1時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- 波特率:一般可選的設(shè)置項(xiàng)包括4800、9600、115200等,常用的波特率為9600。
USART_InitStructure.USART_BaudRate = 9600;
- 數(shù)據(jù)字長:可選8位或9位,常用的是8位。
USART_InitStructure.USART_BaudRate = 9600;
- 停止位:可選0.5、1、1.5、2個(gè),常用的是1個(gè)停止位。
USART_InitStructure.USART_BaudRate = 9600;
- 奇偶校驗(yàn):可選無校驗(yàn)、奇校驗(yàn)和偶校驗(yàn),常用的是無校驗(yàn)。
USART_InitStructure.USART_Parity = USART_Parity_No;
- 模式:可選發(fā)送、接收,或者同時(shí)啟用,一般都是同時(shí)啟用。
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- 硬件流控:可選有使能RTS、使能CTS、同時(shí)使能、不使能,一般選擇不使能。
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- 初始化配置
USART_Init(USART1, &USART_InitStructure);
- 使能
USART_Cmd(USART1, ENABLE);
2. 處理
處理分為接收和發(fā)送。
接收處理通常放在中斷中,中斷服務(wù)函數(shù)名稱為USART1_IRQHandler(),調(diào)用庫函數(shù)USART_ReceiveData()得到接收的數(shù)據(jù),并自動(dòng)清除接收中斷標(biāo)志位;
發(fā)送直接調(diào)用庫函數(shù)USART_SendData()即可,發(fā)送完成之后會(huì)調(diào)用函數(shù)來獲取相應(yīng)標(biāo)志來實(shí)現(xiàn)發(fā)送完成等待功能,即USART_SendData()函數(shù)返回時(shí),相應(yīng)的數(shù)據(jù)已經(jīng)確保發(fā)送完成,并可發(fā)送下一個(gè)數(shù)據(jù),發(fā)送不同類型的數(shù)據(jù)可以封裝成不同的函數(shù),但最終都是調(diào)用USART_SendData()函數(shù)。
接收:
發(fā)送:
//發(fā)送一個(gè)字節(jié) void Usart_SendByte(USART_TypeDef * pUSARTx, uint8_t ch) {//發(fā)送一個(gè)字節(jié)數(shù)據(jù)到USARTUSART_SendData(pUSARTx,ch);//等待發(fā)送數(shù)據(jù)寄存器為空,即發(fā)送完成while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } //發(fā)送一個(gè)數(shù)組 void Usart_SendArray(USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num) //發(fā)送字符串 void Usart_SendString(USART_TypeDef * pUSARTx, char *str)完整代碼(僅自己編寫的部分)
void NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中斷控制器組選擇 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART為中斷源 */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;/* 搶斷優(yōu)先級*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子優(yōu)先級 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中斷 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure); }void USART_Config(uint32_t baudrate) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打開串口GPIO的時(shí)鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 打開串口外設(shè)的時(shí)鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 將USART Tx的GPIO配置為推挽復(fù)用模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 將USART Rx的GPIO配置為浮空輸入模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置串口的工作參數(shù)// 配置波特率USART_InitStructure.USART_BaudRate = baudrate;// 配置 幀數(shù)據(jù)字長USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits = USART_StopBits_1;// 配置校驗(yàn)位USART_InitStructure.USART_Parity = USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 配置工作模式,收發(fā)一起USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(USART1, &USART_InitStructure);// 串口中斷優(yōu)先級配置NVIC_Configuration();// 使能串口接收中斷USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 使能串口USART_Cmd(USART1, ENABLE); }//發(fā)送一個(gè)字節(jié) void Usart_SendByte(USART_TypeDef * pUSARTx, uint8_t ch) {//發(fā)送一個(gè)字節(jié)數(shù)據(jù)到USARTUSART_SendData(pUSARTx,ch);//等待發(fā)送數(shù)據(jù)寄存器為空,即發(fā)送完成while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }//發(fā)送數(shù)組 void Usart_SendArray(USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num) {uint8_t i;for(i = 0; i < num; i++){/* 發(fā)送一個(gè)字節(jié)數(shù)據(jù)到USART */Usart_SendByte(pUSARTx, array[i]);}/* 等待發(fā)送完成 */while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC)==RESET); }//發(fā)送字符串 void Usart_SendString(USART_TypeDef * pUSARTx, char *str) {uint32_t k = 0;do{Usart_SendByte(pUSARTx, *(str + k));k++;} while(*(str + k)!='0');/* 等待發(fā)送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET); }//發(fā)送16位數(shù) void Usart_SendHalfWord(USART_TypeDef * pUSARTx, uint16_t ch) {uint8_t temp_h, temp_l;/* 取出高八位 */temp_h = (ch & 0xFF00) >> 8;/* 取出低八位 */temp_l = ch & 0xFF;/* 發(fā)送高八位 */USART_SendData(pUSARTx, temp_h);while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);/* 發(fā)送低八位 */USART_SendData(pUSARTx, temp_l);while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }// 串口中斷服務(wù)函數(shù) void USART1_IRQHandler(void) {uint8_t ucTemp;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ucTemp = USART_ReceiveData(USART1);USART_SendData(USART1, ucTemp);} }int main(void) {USART_Config(9600);Usart_SendString(USART1, "Hello World!n");while(1){} }仿真結(jié)果
1. 發(fā)送
編譯完成后,點(diǎn)擊
開始仿真,點(diǎn)擊
,打開串口監(jiān)視串口(點(diǎn)擊右側(cè)的箭頭可以選擇第幾個(gè)串口),然后運(yùn)行程序,可以在串口監(jiān)視窗口看到串口發(fā)送的信息。
2. 接收
如果想要仿真串口接收,需要使用虛擬串口軟件vspd,下載安裝完成后,運(yùn)行該軟件:
可以看到左側(cè)有COM1-5共 5個(gè)物理串口,點(diǎn)擊右側(cè)的添加端口,可以添加COM6和COM7兩個(gè)虛擬串口,并自動(dòng)連接這兩個(gè)串口。
此時(shí)可以打開2個(gè)串口工具,分別設(shè)置為COM6和COM7,并分別發(fā)送數(shù)據(jù),看看對方是否能夠正常接收,如果可以,表示虛擬串口添加并連接成功,此時(shí)在串口工具中關(guān)閉COM6。
運(yùn)行KEIL,并開始仿真后,在COMMAND串口中輸入
MODE COM6 9600,0,8,1
ASSIGN COM6 <S1IN> S1OUT
第一條命令設(shè)置COM6波特率9600,無校驗(yàn)位,8個(gè)數(shù)據(jù)位,1個(gè)停止位,注意這里的設(shè)置應(yīng)該與程序中串口的設(shè)置保持一致。
第二條命令將COM6和單片機(jī)的第一個(gè)串口進(jìn)行綁定,即單片機(jī)第一個(gè)串口的收發(fā)數(shù)據(jù)通過計(jì)算機(jī)的COM6進(jìn)行收發(fā)。
此時(shí)在串口工具打開COM7,并通過串口工具發(fā)送數(shù)據(jù),程序即可接收到發(fā)送的數(shù)據(jù)。
從上圖可以看到從COM7發(fā)送了一個(gè)A給單片機(jī),單片機(jī)接收到了A,并將A又發(fā)送出去,COM7接收到了A。
因此,通過虛擬串口軟件,即可在無開發(fā)板、無串口線、無串口設(shè)備的情況下,通過串口工具即可調(diào)試串口接收及發(fā)送程序,實(shí)現(xiàn)純軟件環(huán)境調(diào)試。
學(xué)習(xí)資料分享交流群:1093776732 入群有全套學(xué)習(xí)視頻資料電子書免費(fèi)贈(zèng)送!
參考資料:
嵌入式開發(fā)直播課 - STM32 USART串口的應(yīng)用?www.makeru.com.cn物聯(lián)網(wǎng)開發(fā)入門直播課 - 基于STM32講解串口操作?www.makeru.com.cn物聯(lián)網(wǎng)開發(fā)入門直播課 - 通過Z-stack協(xié)議棧實(shí)現(xiàn)串口透傳?www.makeru.com.cn嵌入式開發(fā)直播課 - 帶你揭曉STM32定時(shí)器深藏不露的絕技?www.makeru.com.cn物聯(lián)網(wǎng)STM32入門 - 帶你揭曉STM32定時(shí)器深藏不露的絕技?www.makeru.com.cn總結(jié)
以上是生活随笔為你收集整理的vc++ cserialport 打开多个串口_STM32之USART串口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jmeter压测_简单七步,快速入门 J
- 下一篇: mysql 服务无法启动 没有报告任何错