USART——串口通訊

開發平臺

  • 野火F429開發板
  • 標準庫

通訊基本概念

  • 同步通訊和異步通訊
    同步通訊和異步通訊的區別在於有沒有時鐘信號線
  • 全雙工、半雙工、單工通訊
    全雙工可以收發同時進行
    半雙工可以收發但不可同時進行
    單工只能收或發

USART

  • 三大時序:USART、I2C、SPI,USART是其中之一了
  • USART時序:起始位爲低電平、然後發送數據8位數據是沒有校驗位的,9位數據是有校驗位的、停止位爲高電平。時序如下圖:(字長爲8)
    在這裏插入圖片描述

現在我使用串口一般都是打印調試信息或者藍牙通訊 ,只會用到TX和RX,不需要用到時鐘信號線,所以是異步半雙工
如果想要操作寄存器,那就要看功能框圖了
在這裏插入圖片描述
1.TX發送數據引腳、RX接受數據引腳,所以要把引腳配置爲串口複用引腳(每個串口對應的引腳都不一樣,這樣查看手冊)
2.發送數據寄存器和接收數據寄存器,還有發送移位寄存器和接受移位寄存器
發送數據時,發送寄存器將數據一位位的移向移位寄存器發送出去
接收數據時,將數據接收到移位寄存器然後再移向接收寄存器
3.控制寄存器CR1:要使能USART、設置數據位(字長)、是否開啓校驗位、奇校驗還是偶校驗、作爲發送器還是作爲接收器(使能)
在這裏插入圖片描述
4.波特率設置,直接操作寄存器的時候要自己算出數值,然後寫入寄存器,如果用標準庫就不需要計算了,已經算好了。公式如下:
OVER8:過採樣模式,根據選擇的模式去更改權位(計算小數的時候)
在這裏插入圖片描述
使用標準庫的話上面的瞭解一下就好了

  • 串口的四個參數:波特率、數據位、校驗位、停止位。
  • 波特率:每秒中傳輸了多少個碼元
  • 數據位:八位或者九位,八位是沒有校驗位九位是有校驗位
  • 使能了校驗位之後每個字符的數據幀格式:啓動位+數據位+校驗位+停止位
    沒有使能校驗位每個字符的數據幀格式:啓動位+數據位+停止位
  • 停止位:表示數據已經發送完成了,停止位長傳輸準確率高,效率低 停止位分爲0.5位、1位、1.5位、2位
    0.5位和1.5位用在智能卡模式,一般情況下用1位停止位,2位停止位一般用於USART模式、單線模式、調制解調器模式。
  • 一般情況:波特率:115200、數據位:8位、無校驗位、停止位:1位
    要想實現通訊,發送設備和接受設備波特率、數據位、校驗位、停止位必須相同纔可實現通訊
    1.初始化串口的引腳
    2.配置串口的參數
    3.編寫發送字符串函數
    4.重定向printf函數和scanf函數
    什麼是重定向?簡單來說,你喝水要喝進肚子裏,可是你喝的時候是喝進腦子裏的,你必須重定向才能讓水喝進肚子裏。

代碼如下:

#ifndef __USART__H
#define __USART__H

#include "main.h"

#define USART_TX_CLOCK                  RCC_AHB1Periph_GPIOA
#define USART_RX_CLOCK                  RCC_AHB1Periph_GPIOA
#define USART_TX_PORT                   GPIOA
#define USART_RX_PORT                   GPIOA
#define USART_TX_PINSOURCE              GPIO_PinSource9            
#define USART_RX_PINSOURCE              GPIO_PinSource10           
#define USART_AF                         GPIO_AF_USART1
#define USART_TX_PIN                    GPIO_Pin_9
#define USART_RX_PIN                    GPIO_Pin_10

#define USART_CLOCK_Cmd()               RCC_APB2PeriphClockCmd(USART_CLOCK,ENABLE)
#define USART_CLOCK                     RCC_APB2Periph_USART1
#define USART                           USART1  
#define BAUDRATE                        115200                 

void USART_GPIO_Config(void);
void USART_Config(void);
void USATR_Sendbyte(uint16_t data);
void USART_Sendstring(char *string);
int fputc(int ch, FILE *f);


#endif
#include "usart.h"

void USART_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    /*開USART引腳複用時鐘*/
    RCC_AHB1PeriphClockCmd(USART_TX_CLOCK|
                           USART_RX_CLOCK,ENABLE);
    /*
    **複用模式
    **不上拉不下拉
    **TX->PB6    RX->PB7
    */
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Pin=USART_TX_PIN;
    GPIO_Init(USART_TX_PORT,&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Pin=USART_RX_PIN;
    GPIO_Init(USART_RX_PORT,&GPIO_InitStruct);
    /*設置複用功能*/
    GPIO_PinAFConfig(USART_TX_PORT,USART_TX_PINSOURCE,USART_AF);
    GPIO_PinAFConfig(USART_RX_PORT,USART_RX_PINSOURCE,USART_AF);
}

void USART_Config(void)
{
    USART_InitTypeDef USART_InitStruct;
    /*引腳配置*/
    USART_GPIO_Config();
    /*開串口時鐘*/
    USART_CLOCK_Cmd();
    /*
    **波特率115200
    **發送和接收模式
    **無校驗位
    **停止位爲1
    **8位數據位
    **不使用硬件流
    */
    USART_InitStruct.USART_BaudRate=BAUDRATE;
    USART_InitStruct.USART_Parity=USART_Parity_No;
    USART_InitStruct.USART_StopBits=USART_StopBits_1;
    USART_InitStruct.USART_WordLength=USART_WordLength_8b;
    USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
    USART_Init(USART,&USART_InitStruct);
    /*使能串口*/
    USART_Cmd(USART,ENABLE);
}

void USATR_Sendbyte(uint16_t data)
{
    USART_SendData(USART,data);
    while(USART_GetFlagStatus(USART,USART_FLAG_TXE)==RESET);
}

void USART_Sendstring(char *string)
{
    unsigned int i=0;
    do
    {
        USATR_Sendbyte(*(string+i));
        i++;
    } while (*(string+i)!='\0');

    while(USART_GetFlagStatus(USART,USART_FLAG_TC)==RESET);
}


///重定向c庫函數printf到串口,重定向後可使用printf函數

int fputc(int data, FILE *f)
{
		/* 發送一個字節數據到串口 */
		USART_SendData(USART,(uint8_t) data);
		
		/* 等待發送完畢 */
		while (USART_GetFlagStatus(USART, USART_FLAG_TXE) == RESET);		
	
		return (data);
}

int fgetc(FILE *f)
{
    /*等待接受完畢*/
    while(USART_GetFlagStatus(USART,USART_FLAG_RXNE)==RESET);

    return (USART_ReceiveData(USART));
}
發佈了17 篇原創文章 · 獲贊 20 · 訪問量 5211
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章