前邊我們學的都是通用的功能,例如GPIO、中斷,現在我們要學習的是某一個特定的功能。典型的就是通訊功能。其中,最簡單的通訊協議就是串口了。
一、串口_通訊基礎知識
1.1 串行與并行
按數據傳送的方式分類的。
串行通信一位一位傳輸,并行則是8位(16、32位)同行。(按位傳輸)
頻率越高,電流產生電磁場,干擾越大。
早期用的硬盤ATA,后來有了SATA硬盤(S是串行的意思)
傳輸接口基本上都是串行。
1.2 單工、半雙工、全雙工
單工傳輸:數據單向傳輸,只能A-->B
半雙工傳輸:數據雙向傳輸,但同一時刻只能傳一個方向,不可同時。如對講機!
全雙工傳輸:至少2條線,同時雙向傳輸。
1.3 同步和異步
同步和異步區別:有無時鐘!
同步至少兩根線:一個傳輸時鐘信號,一個傳輸數據信號
異步只有一根線,單工或半雙工
二、串口通訊:
兩根線實現全雙工
串口通訊協議:
波特率:
奇偶校驗位:
奇校驗:所有1加起來是一個奇數
偶校驗:所有1加起來是一個偶數
空閑位:
分數波特率的產生
小數部分:DIV_Fraction
整數部分:DIV_Mantissa
狀態寄存器SR
IDEA:0沒有檢測到空閑 ,1檢測到空閑總線
TXE:
TC:
RXNE:
控制寄存器1USART_CR1
控制寄存器2USART_CR2
三、USART外設
同步異步收發器,串行通信設備,全雙工數據交換。
UART與USART相比去掉了同步通訊功能
USART1通訊速率最高,可以達到4.5Mbps。2,3,4,5最高只有USART1的一半。
我們在stm32中,調試口用USART1.
以前臺式電腦,就是以上的Bj9接口.?
UART是異步收發器。UART,有時指設備,有時指協議。
RS485兩根線,作差分傳輸,半雙工。
四、波特率設置
分數波特率的產生
接收器和發送器的波特率在USARTDIV的整數和小數寄存器中的值應設置成相同。
fck=72MHZ
如果DIV_Mantissa=27,整數是27,DIV_Fraction=12(USART_BRR=0x1BC),小數是12.
例二是我們要常用的,可以配波特率。
五、串口所用寄存器
TDR
RDR
檢測到空閑幀,IDLE置1.
六、寄存器實現
目前很多電腦沒有串口接口,為了使用串口,我們自制的下載器STLink2.1擁有USB轉串口的功能。
所用引腳:
上位機,串口調試工具:
文末給大家分享的資料包里有。我們能通過串口工具向stm32發信息。當然stm32要想收到,必須有相應的接收程序。
2.1 創建工程
?
創建新的外設代碼文件USART
?
有了新的文件,KEIL里面必須配置上。
?
之后便是通過VSCODE打開。
2.2 代碼編寫?
將usart.c和usart.h,預處理編碼做好。聲明需要編寫的函數。
我們用的usart1在APB2系統總線上。
我們也要開啟GPIO的時鐘,因為有輸入輸出。
usart.h
#ifndef __USART_H
#define __USART_H#include "stm32f10x.h"
//初始化
void USART_Init(void);//發送一個字符
void USART_SendChar(uint8_t ch);//接收一個字符
uint8_t USART_ReceiveChar(void);#endif
usart.c?
#include "usart.h"//初始化
void USART_Init(void)
{//開啟時鐘RCC->APB2ENR |= RCC_APB2ENR_USART1EN;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//GPIO工作模式// PA9:TX 復用推挽輸出,CNF=10,MODE=11GPIOA->CRH |= GPIO_CRH_MODE9;GPIOA->CRH |= GPIO_CRH_CNF9_1;GPIOA->CRH &= ~GPIO_CRH_CNF9_0;// PA10:RX 浮空輸入,CNF=01,MODE=00GPIOA->CRH &= ~GPIO_CRH_MODE10;GPIOA->CRH &= ~GPIO_CRH_CNF10_1;GPIOA->CRH |= GPIO_CRH_CNF10_0;//串口模塊設置//設置波特率 115200USART1->BRR = 0x271;//使能串口和收發模塊USART1->CR1 |= USART_CR1_UE;USART1->CR1 |= (USART_CR1_TE|USART_CR1_RE);//配置數據幀格式USART1->CR1 &=~ USART_CR1_M; //長度為8位的數據,沒有校驗位USART1->CR1 &=~ USART_CR1_PCE; //無校驗,不使用校驗位USART1->CR2 &=~ USART_CR2_STOP; //1位停止位}//發送一個字符
void USART_SendChar(uint8_t ch)
{//判斷TDR是否為空,必須等待TDR為空才能寫入數據,也就是繼續發送while((USART1->SR & USART_SR_TXE)==0){}//將要發送的數據寫入TDRUSART1->DR = ch;
}//接收一個字符
uint8_t USART_ReceiveChar(void)
{//判斷RDR是否非空。必須有數據才能讀取數據while((USART1->SR & USART_SR_RXNE)==0){}//讀取接收到的數據,返回return USART1->DR;
}
main.c
#include "usart.h"
#include "delay.h"int main(void)
{//1.初始化USART_Init();//發送單個字符USART_SendChar('A');USART_SendChar('B');USART_SendChar('C');USART_SendChar('\n');while(1){//不停發送字符USART_SendChar('D');USART_SendChar('\n');//延時Delay_ms(500);}}
?
還可以看看接收,接收到我們在軟件中發送的,再次發到軟件。
這樣可能不太明顯,如果我們在軟件上位機發給stm32一個小寫字母,我們32端收到后,將其轉化為大寫字母,再次發到上位機。因為小寫字母與大寫字母在ASCII值相差32,所以只要做差即可
?
七、資料
stm32開發官方版下載丨最新版下載丨綠色版下載丨APP下載-123云盤