当前位置:网站首页>串口實驗——簡單數據收發
串口實驗——簡單數據收發
2022-07-07 08:58:00 【一只大喵咪1201】
作者:一只大喵咪1201
專欄:《STM32學習》
格言:你只管努力,剩下的交給時間!
描述
串口作為 MCU 的重要外部接口,同時也是軟件開發重要的調試手段,其重要性不言而喻。現在基本上所有的 MCU 都會帶有串口,STM32 自然也不例外。
STM32 的串口資源相當豐富的,功能也相當强勁。本喵使用的STM32F103ZET6 最多可提供 5 路串口,有分數波特率發生器、支持同步單線通信和半雙工單線通訊、支持 LIN、支持調制解調器操作、智能卡協議和 IrDA SIR ENDEC 規範、具有 DMA等。
接收狀態標記
#define USART_REC_LEN 200 //定義最大接收字節數 200
#define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
extern u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節.末字節為換行符
extern u16 USART_RX_STA; //接收狀態標記
在官方提供的庫函數usart.h中定義了最大接收字節數,是200個字節,而且創建了一個數組,該數組大小是200個字節,每接收一個字節的數據就放入到這個數組中。
而且使用到了一個變量USART_RX_STA,這是一個體些接收狀態的變量,它的大小是16個比特比特,也就是倆個字節大小。
這是它每一比特代錶的意義。
- 0到13比特存放的是接收到的有效數據個數,每接收到一個有效數據,就會加1。
- 第14比特代錶是否接受到0X0D數據,也就是回車字符。我們對該串行通信規定,是以回車(0X0D)換行(0X0A)字符結束通信的。如果接受到的數據是0X0D就將該比特置為1。
- 第15比特代錶是否完成接收。如果在接收到的數據是0X0D(回車字符)之後的一個數據是0X0A(換行字符),說明接收完成了,就將該比特置為1。
以上規定是我們在通信之前雙方之間約定好的,通信雙方投按照這個約定來。
函數配置
我們這個實驗就僅僅實現簡單的數據收發。5個串口中,我們選擇串口1(UASRT1)實現這個實驗。
在本喵的文章串口寄存器函數配置中曾詳細的講到過如何配置串口,在這裏本喵便直接去配置,不再講述原因。
- 使能GPIOA和USART1的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
- 配置GPIOA口
GPIO_InitTypeDef GPIO_InitStructure;
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
USART_Init(USART1, &USART_InitStructure); //初始化串口1
- 配置串口
USART_InitTypeDef USART_InitStructure;
//USART 初始化設置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8比特數據格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止比特
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗比特
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式
- 配置中斷優先級
NVIC_InitTypeDef NVIC_InitStructure;
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器
- 開啟接收中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷
- 串口使能
USART_Cmd(USART1, ENABLE); //使能串口1
- 編寫中斷服務函數
void USART1_IRQHandler(void) //串口1中斷服務程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾)
{
Res =USART_ReceiveData(USART1); //讀取接收到的數據
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始
else USART_RX_STA|=0x8000; //接收完成了
}
else //還沒收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
OSIntExit();
#endif
}
- 在進入到中斷函數後創建一個1個字節大小的一個變量Res,用於存放接收到的數據。
- 需要判斷一下是否發生的是接收中斷,如過是接收中斷則繼續執行中斷服務程序,如果是別的中斷則不執行中斷服務程序。
- 判斷一下接收狀態標志中的最高比特是否為1,如果是1則說明已經完成了數據的接收,就不用再接收了,如果是0則說明沒有完成數據接收,需要繼續接收。
- 判斷第14比特是否為1,是1則說明上一個數據是0X0D也就是回車字符,這時就要接著判斷下一個數據是否是0X0A也就是換行字符,如果不是換行字符,說明這個數據接收錯了,需要重新接收,如果是換行字符就說明數據接收完成了,需要將最高比特置1。
- 判斷第14比特是0的時候,說明數據仍然在不停的接收,在接收到一個數據時就要判斷一下是否是0X0D也就是回車字符,並且設置相應的標志比特。
- 當上一個數據和這一個數據都不是0X0D的時候,將接收到的數據放在數組中,數組的下標就是0到13比特中有效數據的個數。
以上的函數配置過程是不需要我們一行代碼一行代碼寫的,在ST官方提供的庫函數usart.c中有這些函數,我們直接使用即可。
- 編寫主程序
主程序中的代碼是需要我們親自編寫的
#include "delay.h"
#include "usart.h"
#include "led.h"
int main(void)
{
u8 len = 0;//存放數據個數
u8 t = 0;//循環控制變量
LED_Init();//LED0初始化
delay_init();//延時初始化
uart_init(115200);//串口初始化,波特率為115200
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//優先級分組使用第二組
while(1)
{
//數據接收完成時發送
if(USART_RX_STA&0x8000)
{
len = USART_RX_STA&0x3fff;//得到數據長度
printf("\r\n您發送的數據為:\r\n");
//發送所有數據
for(t = 0; t < len; t ++)
{
USART_SendData(USART1,USART_RX_BUF[t]);//發送一個數據
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET)
{
;//一個數據未發送完便一直等待
}
}
printf("\r\n\r\n");
USART_RX_STA = 0;//數據都發送完後將狀態比特清0
}
//數據接收未完成時等待數據接收
else
{
printf("\r\n請輸入數據,按回車結束:\r\n");
while((USART_RX_STA&0x8000)==0)
{
LED0 = !LED0;
delay_ms(500);//led燈閃爍,等待數據輸入
}
}
}
}
這便是串口實驗的所有代碼。
效果展示
在串口調試助手上,輸入內容後點發送,接收窗口就會顯示輸入的內容。
在沒有輸入時,開發板上的LED燈在不停閃爍,這裏就不拍開發板的照片了。
總結
該實驗主要在於主程序的編寫,因為其他初始化函數都是ST官方提供的庫函數,我們如果需要使用到的是其他串口或者有其他的要求,只需要對庫函數稍作修改即可。
边栏推荐
- [Yugong series] February 2022 U3D full stack class 006 unity toolbar
- 【ChaosBlade:根据标签删除POD、Pod 域名访问异常场景、Pod 文件系统 I/O 故障场景】
- 最长上升子序列模型 AcWing 1017. 怪盗基德的滑翔翼
- Screen automatically generates database documents
- Goldbach conjecture C language
- 【ChaosBlade:节点 CPU 负载、节点网络延迟、节点网络丢包、节点域名访问异常】
- H3C VXLAN配置
- Common operating commands of Linux
- Greenplum6.x重新初始化
- 徽商期货公司评级是多少?开户安全吗?我想开户,可以吗?
猜你喜欢
Three updates to build applications for different types of devices | 2022 i/o key review
A bug using module project in idea
MySQL主从延迟的解决方案
Esp32-ulp coprocessor low power mode RTC GPIO interrupt wake up
Output a spiral matrix C language
Reading notes of pyramid principle
Ppt template and material download website (pure dry goods, recommended Collection)
Category of IP address
使用Typora编辑markdown上传CSDN时图片大小调整麻烦问题
Calf problem
随机推荐
Mock. JS usage details
Lenovo hybrid cloud Lenovo xcloud: 4 major product lines +it service portal
Shell script for changing the current folder and the file date under the folder
模拟卷Leetcode【普通】1705. 吃苹果的最大数目
Oracle makes it clear at one time that a field with multiple separators will be split into multiple rows, and then multiple rows and columns. Multiple separators will be split into multiple rows, and
Greenplum 6.x monitoring software setup
Explain Huawei's application market in detail, and gradually reduce 32-bit package applications and strategies in 2022
C language for calculating the product of two matrices
平台化,强链补链的一个支点
模拟卷Leetcode【普通】1567. 乘积为正数的最长子数组长度
MySQL主从延迟的解决方案
Enterprise manager cannot connect to the database instance
模拟卷Leetcode【普通】1557. 可以到达所有点的最少点数目
Frequently Asked Coding Problems
How to add a mask of a target in a picture
Mountaineering team (DFS)
xray的简单使用
[Yugong series] February 2022 U3D full stack class 005 unity engine view
Implement custom memory allocator
Reflections on the way of enterprise IT architecture transformation (Alibaba's China Taiwan strategic thought and architecture practice)