色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

STM32速成筆記(5)—串口通信

冬至子 ? 來源:二土電子 ? 作者:二土電子 ? 2023-10-24 09:16 ? 次閱讀

一、什么是串口通信

串口通信是指外部設備與主控芯片之間,通過數據信號線、地線等,按位進行數據傳輸的一種通信方式,屬于串行通信方式。串行通信是指使用一條數據線依次逐位傳輸數據,每一位數據占據固定長度的時間。可以看一下簡單的串行通信示意圖。

圖片

串口通信示意圖

二、串口通信有什么用

這里簡單列舉一下串口通信的用途

  • ? 下載程序

  • ? 外設與單片機通信 單片機給外設發送一些指令或者配置信息,外設給單片機回傳一些信息。

  • ? 打印信息 比如將ADC采集到的電壓發送給上位機的串口調試助手,或者實時監測某一個變量的變化。

    三、STM32的串口通信

    普中核心板上使用的STM32F103ZET6有三個USART,兩個UART,他們都支持串口通信功能。USART(通用同步異步收發器)與UART(通用異步收發器)相比,多了一個同步功能,可以認為USART是UART的增強型。

    四、串口通信相關概念

    44.1 波特率

    引用專業的說法,波特率表示單位時間內傳送的碼元符號的個數,它是對符號傳輸速率的一種度量。其實意思就是波特率表示1s內傳輸碼元的個數。在單片機中數字都是二進制的01表示的,所以波特率可以說是1s內傳輸01的個數。常見的波特率有38400、9600和115200等。

波特率通常由波特率發生器產生,串口要想實現收發首先要有波特率發生器,網上介紹波特率發生器的作用是輸入時鐘轉換出需要的波特率CLK。個人理解,波特率發生器就是提供一個時鐘,這樣才能發送出正確波特率的信息,比如1和0需要多久的高/低電平表示。

在串口通信時如果收發雙方波特率不相同會導致通信失敗,要么是接收不到,要么是接收到的是亂碼。

4.2 全雙工和半雙工

  • ? 全雙工可以簡單解釋為,我在接收消息的同時,你也可以發送消息。
  • ? 半雙工可以簡單解釋為,我在接收消息時,沒辦法發送消息。類似于對講機,你說話時占用了信道,對方無法跟你講話,只有當你說完了,他才可以對你講話。

4.3 同步通信和異步通信

同步通信和異步通信的區別在于通信雙方是否需要時鐘同步。同步通信的接收雙方之間除了需要數據線之外,還需要一根時鐘線,而異步通信不需要。關于二者的詳細定義與區別,請大家自行搜索。

五、硬件連接

串口通信只需幾條線即可在兩個系統間交換信息,特別適用于計算機與計算機、計算機與外設之間的通信,常用的串口通信接口標準有很多,比如RS-232C、RS-232、RS-485等。但是放在單片機開發里,最簡單的串口通信就是用四根線VCC、GND、TXD和RXD實現通信。

圖片

串口通信硬件連接示意圖

普中核心板上常用的是USART1,其引腳對應如下

  • ? TXD——PA9

  • ? RXD——PA10

    六、串口通信程序配置

    下面以配置USART1為例,來簡單展示一下USART的配置方法。

    66.1 使能串口時鐘和GPIO時鐘

// 使能USART1,GPIOA時鐘
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);

6.2 初始化GPIO

初始化USART1用到的GPIO。TXD引腳設置為復用推挽式輸出,RXD引腳設置為輸入浮空。

// 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

6.3 初始化串口參數

庫函數提供了一個結構體,用于初始化串口。其中包括

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;   // 收發模式
    USART_Init(USART1, &USART_InitStructure);   // 初始化串口1

6.4 使能串口

USART_Cmd(USART1, ENABLE);   // 使能串口1

6.5 串口接收中斷

平時開發過程中經常需要開啟串口接收中斷,配置串口接收中斷的方法與上一篇的外部中斷有些類似,主要包括以下步驟

  • ? 配置中斷分組(通常在main函數中初始化中配置)
  • ? 設置中斷優先級
  • ? 使能中斷

配置中斷優先級

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);   // 開啟串口接收中斷

6.6 串口接收中斷服務函數

通常接收到的數據會是一幀,很少是一個單獨的字符,這里給出一個接收一幀數據的串口中斷服務函數。需要注意的是,在初始化串口時,需要使能空閑中斷。

使能空閑中斷的程序如下

USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);   // 使能空閑中斷
/*
 *==============================================================================
 *函數名稱:USART1_IRQHandler
 *函數功能:USART1中斷服務函數
 *輸入參數:無
 *返回值:無
 *備  注:無
 *==============================================================================
 */
u32 gReceCount = 0;   // 接收計數變量
u32 gClearCount = 0;   // 清空接收數組計數變量
u8 gReceFifo[1500];   // 接收數組
u8 gReceEndFlag = 0;   // 接收完成標志位 

void USART1_IRQHandler(void)  
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)   //接收到一個字節  
    {
        gReceFifo[gReceCount++] = USART_ReceiveData(USART1);
    }
    else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)   //接收到一幀數據
    {
        USART1- >SR;   // 先讀SR
        USART1- >DR;   // 再讀DR
        
        gReceEndFlag = 1;   // 接收完成標志置1 
    } 
}

接收完成后,接收完成標志位會置1。此時,對接收到的幀進行解析處理。解析完成后需要清除接收數組,同時,不要忘記清除接收完成標志位。

/*
 *==============================================================================
 *函數名稱:Uart_Rece_Pares
 *函數功能:解析串口接收內容
 *輸入參數:無
 *返回值:無
 *備  注:無
 *==============================================================================
 */
void Uart_Rece_Pares(void)   // 串口接收內容解析函數
{
    if (gReceEndFlag  == 1)   // 如果接收完成
    {
        // 解析接收內容
        
        // 清空接收數組
        for (gClearCount = 0;gClearCount < gReceCount;gClearCount ++)
        {
            gReceFifo[gClearCount] = ' ';
        }
            
        gReceEndFlag = 0;   // 清除接收完成標志位
        gReceCount = 0;   // 清零接收計數變量
    }
}

6.7 串口發送函數

//串口發送函數
void USART1_Send(u8*str)
{
    u8 index=0;
    do
    {
        USART_SendData(USART1,str[index++]);
        while(USART1,str[index++]);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
    }
    while(str[index]!=0);
}

其實這里最根本的USART_SendData()本質就是將數據搬運到串口發送的寄存器。當然除了直接用發送函數發送,也可以直接重定向之后用printf發送,這里就不詳細介紹了,有需要的友友可以直接去看普中或者正點的教程視頻

七、拓展

7.1 printf重定向

關于重定向的概念這里就不再做介紹了,重定向之后就可以在程序中使用printf直接打印或者發送字符串,不再需要串口發送函數。重定向的方法就是在串口的.c文件中添加下面的程序

// 加入以下函數可以使用printf
#pragma import(__use_no_semihosting)             
// 標準庫需要的支持函數                 
struct __FILE 
{ 
    int handle; 
}; 

FILE __stdout;       
//定義_sys_exit()以避免使用半主機模式    
void _sys_exit(int x) 
{ 
    x = x; 
} 
//重定義fputc函數 
int fputc(int ch, FILE *f)
{      
    while((USART1- >SR&0X40)==0);//循環發送,直到發送完畢   
    USART1- >DR = (u8) ch;      
    return ch;
}

7.2 接收幀解析

這里的接收幀解析比較簡單,比如有些項目要求接收到某些特定字符執行某些操作。這時需要根據接收幀的長度和固定位置的字符來解析命令。

比如項目要求上位機(電腦)發送“BEEP ON”時,蜂鳴器響。這時在解析時只要接收到長度為6,第5和第6個字符分別為“O”,“N”時,開啟蜂鳴器即可。

// 解析接收內容
if (gReceCount == 6 && gReceFifo[5] == 'O' && gReceFifo[6] == 'N')
{
   // 開啟蜂鳴器
}

當然上面的只是粗略的卡命令,也可以寫的更詳細。

八、實戰項目

8.1 前期準備

  • ? CH340驅動
  • ? USB轉TTL,用于單片機與電腦的通信
  • ? 串口調試助手

剛買來的普中核心板,不拔短接片的話可以直接通過USB下載程序,或者與電腦進行串口通信,串口為USART1。注意一定要插圖中標出來的USB接口,另一個只能用來供電

圖片

串口通信跳線帽連接

8.2 項目要求

  • ? 單片機上電發送“Sys Ready!”

  • ? 電腦串口助手發送“LED1 ON”(帶回車換行),LED1點亮,同時單片機回復“OK!”

  • ? 電腦串口助手發送“LED1 OFF”(帶回車換行),LED2熄滅,同時單片機回復“OK!”

    88.3 串口程序

    8.3.1 初始化串口

    首先是串口初始化程序,需要開啟接收中斷和空閑中斷。

/*
 *==============================================================================
 *函數名稱:uart_init
 *函數功能:初始化USART1
 *輸入參數:bound:波特率
 *返回值:無
 *備  注:可以修改成輸入初始化哪個USART
 *==============================================================================
 */
void uart_init(u32 bound)
{
    // 相關結構體定義
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能USART1,GPIOA時鐘
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 

    // 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  

    // 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 初始化設置
    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;   // 收發模式
    USART_Init(USART1, &USART_InitStructure);   // 初始化串口1
  
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);   // 開啟串口接收中斷
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);   // 使能空閑中斷
    
  USART_Cmd(USART1, ENABLE);   // 使能串口1 
}

其次需要加上重定向函數,直接復制上面的即可。

8.3.2 串口接收中斷服務函數

/*
 *==============================================================================
 *函數名稱:USART1_IRQHandler
 *函數功能:USART1中斷服務函數
 *輸入參數:無
 *返回值:無
 *備  注:無
 *==============================================================================
 */
u32 gReceCount = 0;   // 接收計數變量
u32 gClearCount = 0;   // 清空接收數組計數變量
u8 gReceFifo[1500];   // 接收數組
u8 gReceEndFlag = 0;   // 接收完成標志位 

void USART1_IRQHandler(void)  
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)   //接收到一個字節  
    {
        gReceFifo[gReceCount++] = USART_ReceiveData(USART1);
    }
    else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)   //接收到一幀數據
    {
        USART1- >SR;   // 先讀SR
        USART1- >DR;   // 再讀DR
        
        gReceEndFlag = 1;   // 接收完成標志置1 
    } 
}

8.3.3 接收幀解析函數

/*
 *==============================================================================
 *函數名稱:Uart_Rece_Pares
 *函數功能:解析串口接收內容
 *輸入參數:無
 *返回值:無
 *備  注:無
 *==============================================================================
 */
void Uart_Rece_Pares(void)   // 串口接收內容解析函數
{
    if (gReceEndFlag  == 1)   // 如果接收完成
    {
        // 解析接收內容
        if (gReceFifo[6] == 'N')
        {
            Med_Led_StateCtrl (LED1,LED_ON);   // 點亮LED1
            printf ("OK!rn");
        }
        
        if (gReceFifo[6] == 'F' && gReceFifo[7] == 'F')
        {
            Med_Led_StateCtrl (LED1,LED_OFF);   // 熄滅LED1
            printf ("OK!rn");
        }
        
        // 清空接收數組
        for (gClearCount = 0;gClearCount < gReceCount;gClearCount ++)
        {
            gReceFifo[gClearCount] = ' ';
        }
            
        gReceEndFlag = 0;   // 清除接收完成標志位
        gReceCount = 0;   // 清零接收計數變量
    }
}

8.3.3 main函數

int main(void)
{
    Med_Mcu_Iint();   // 系統初始化
    printf ("Sys Ready!rn");
    
    while(1)
  {
        Uart_Rece_Pares ();   // 接收幀解析
    }
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 串口通信
    +關注

    關注

    34

    文章

    1624

    瀏覽量

    55508
  • 異步收發器
    +關注

    關注

    0

    文章

    36

    瀏覽量

    10847
  • 中斷優先級
    +關注

    關注

    0

    文章

    22

    瀏覽量

    9368
  • USART串口
    +關注

    關注

    0

    文章

    32

    瀏覽量

    6818
  • 波特率發生器

    關注

    0

    文章

    11

    瀏覽量

    4028
收藏 人收藏

    評論

    相關推薦

    STM32串口通信

    STM32 串口通信簡單程序 需要串口助手 輸入1點亮LED 輸入0熄滅LED
    發表于 06-14 14:13 ?0次下載

    基于STM32的最小系統及串口通信的實現

    基于STM32的最小系統及串口通信的實現
    發表于 09-25 10:47 ?25次下載
    基于<b class='flag-5'>STM32</b>的最小系統及<b class='flag-5'>串口</b><b class='flag-5'>通信</b>的實現

    基于STM32單片機的串口通信資源

    基于STM32單片機的串口通信資源
    發表于 07-05 09:13 ?21次下載

    STM32最小系統版串口下載/串口通信失敗

    STM32最小系統版串口下載/串口通信失敗
    發表于 11-17 18:21 ?0次下載
    <b class='flag-5'>STM32</b>最小系統版<b class='flag-5'>串口</b>下載/<b class='flag-5'>串口</b><b class='flag-5'>通信</b>失敗

    STM32F103學習筆記串口通信

    STM32F103學習筆記串口通信
    發表于 11-25 09:06 ?71次下載
    <b class='flag-5'>STM32</b>F103學習<b class='flag-5'>筆記</b>三   <b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    stm32串口相互通信

    Stm32f103串口一與串口而相互通信接線:串口一: TTL
    發表于 11-29 16:51 ?30次下載
    <b class='flag-5'>stm32</b>雙<b class='flag-5'>串口</b>相互<b class='flag-5'>通信</b>

    [筆記]|[stm32]|[寄存器存儲器區別]|[PWM]|[串口]|[Timer]stm32f103筆記

    [筆記]|[stm32]|[寄存器存儲器區別]|[PWM]|[串口]|[Timer]stm32f103筆記
    發表于 12-06 18:51 ?10次下載
    [<b class='flag-5'>筆記</b>]|[<b class='flag-5'>stm32</b>]|[寄存器存儲器區別]|[PWM]|[<b class='flag-5'>串口</b>]|[Timer]<b class='flag-5'>stm32</b>f103<b class='flag-5'>筆記</b>

    STM32CubeMX完成USART串口通信

    STM32CubeMX完成USART串口通信
    發表于 12-06 20:36 ?24次下載
    <b class='flag-5'>STM32</b>CubeMX完成USART<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    STM32學習筆記--串口通信

    目錄:一、通信相關知識二、STM32串口三、常用串口寄存器四、串口庫函數配置一、通信相關知識?
    發表于 12-20 19:19 ?6次下載
    <b class='flag-5'>STM32</b>學習<b class='flag-5'>筆記</b>--<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    STM32中的串口通信的基礎知識

    目錄串口通信基本原理并行通信與串行通信串行通信中單工,半雙工和全雙工的區別按通信方式不同又可分為
    發表于 12-24 18:37 ?4次下載
    <b class='flag-5'>STM32</b>中的<b class='flag-5'>串口</b><b class='flag-5'>通信</b>的基礎知識

    STM32下的USART串口通信程序

    STM32的USART串口通信實踐
    發表于 12-24 18:42 ?13次下載
    <b class='flag-5'>STM32</b>下的USART<b class='flag-5'>串口</b><b class='flag-5'>通信</b>程序

    STM32筆記(九)---串口通信

    串口通信(USART)文章目錄串口通信(USART)一、 串口通信協議簡介1-1 概念1-2 常
    發表于 12-28 19:40 ?5次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>筆記</b>(九)---<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    stm32學習筆記串口通信

    本篇文章主要講解一個在開發過程中經常使用到的一個外設—串口串口是絕大多數 MCU 中不可或缺的一個外設,同時也是我們開發中經常使用的一種調試手段,所以在STM32的學習中,串口的配置
    發表于 01-18 08:34 ?4次下載
    <b class='flag-5'>stm32</b>學習<b class='flag-5'>筆記</b>之<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    基于stm32串口通信代碼

    基于stm32串口通信
    發表于 06-15 14:16 ?18次下載

    STM32里的串口通信

    STM32里的串口通信STM32里,串口通信是USART,
    的頭像 發表于 11-10 15:58 ?3142次閱讀
    <b class='flag-5'>STM32</b>里的<b class='flag-5'>串口</b><b class='flag-5'>通信</b>
    主站蜘蛛池模板: 9277在线观看免费高清完整版| 秋霞电影网视频一区二区三区| 狠狠国产欧美在线视频| 国产一区二区三区国产精品| 国产人妻午夜无码AV天堂| 久久99re6国产在线播放| 性做久久久久免费观看| 国产成人精品免费视频下载| 青青视频 在线 在线播放| 最新日本免费一区| 刘梓晨啪啪啪| 最新亚洲人成网站在线影院| 久久99精国产一区二区三区四区 | 日本丝袜护士| YELLOW视频在线观看大全| 男同志vdieos免费| 99精品电影| 欧美阿v在线天堂| 98色精品视频在线| 欧美大jiji| 成人精品视频网站| 十8禁用B站在线看漫画| 国产欧美一区二区三区视频| 亚洲免费视频网站| 久久免费看少妇高潮A片特爽| 中文国产乱码在线人妻一区二区 | 日本高清色片| 国产一卡2卡3卡4卡孕妇网站| 亚洲综合日韩在线2019| 快穿女主有名器的H纯肉黄暴拉文| 69夫妇交友群| 色窝窝亚洲AV在线观看| 亚洲国产精品无码2019| 国产精品1卡二卡三卡四卡乱码| 第四色播日韩AV第一页| 日本另类xxxx| 国产日韩精品一区二区在线观看| 亚洲人交性视频| 美女的隐私蜜桃传媒免费看| 鸭子玩富婆流白浆视频| 成 人 动漫3d 在线看|