[图片] STM32 串口简介 串口作为单片机最重要的外部接口之一,同时又是我们嵌入式开发过程中重要的调试手段之一,其重要性不言而喻。几乎所有的单片机都有串口,STM32 也不例外。STM32 的串口资源相当丰富,功能也相当强劲,我所使用的原子哥的 STM32mini 开发板(STM32F103RCT6),最多可提供 ..

STM32 USART 串口通讯

本贴最后更新于 276 天前,其中的信息可能已经时移世易

STM32 串口简介

串口作为单片机最重要的外部接口之一,同时又是我们嵌入式开发过程中重要的调试手段之一,其重要性不言而喻。几乎所有的单片机都有串口,STM32 也不例外。STM32 的串口资源相当丰富,功能也相当强劲,我所使用的原子哥的 STM32mini 开发板(STM32F103RCT6),最多可提供 5 路串口。

今天的实验

每隔一秒向电脑发送不同字符串

将接收到从电脑发送来的数据返回给电脑

STM32mini 开发板
串口调试助手(Windows),minicom(Linux),超级终端(Windows)

开发工具:sw4stm32

首先新建工程

新建工程

串口设置的一般步骤可以总结为如下几个步骤

串口时钟使能,GPIO 时钟使能
串口复位
GPIO 端口模式设置
串口参数初始化
开启中断并且初始化 NVIC
使能串口
编写中断处理函数

驱动代码

usart.h

#ifndef __USART_H__
#define __USART_H__

#include <stm32f10x.h>
#include <sys/_stdint.h>
 
void USART_INIT(u32 bound);
void USART_SendChar(USART_TypeDef* USARTx, uint8_t data);

void USART_SendStr(USART_TypeDef* USARTx, char *str);
 
#endif

usart.c

#include "usart.h"
#include <misc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_usart.h>
 
//可以使用printf()函数输出
int __io_putchar(int ch) {
    USART_SendChar(USART1, ch);
    return ch;
}
//
发送单个字符
void USART_SendChar(USART_TypeDef* USARTx, uint8_t data){
    USART_SendData(USARTx, data);  // 操作USART_DR寄存器发送单个数据
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);//等待发送寄存器TDR为空,为空时则置1
}
 
//发送字符串函数,支持汉字,编码支持UTF-8
void USART_SendStr(USART_TypeDef* USARTx, char *str){
    uint8_t i = 0;
    do
    {
        USART_SendChar(USARTx, *(str+i));
        i++;
    }while(*(str+i) != '\0');
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);//等待发送完成
}
 
//初始化串口1
void USART_INIT(u32 bound) {
 
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitTypeDef;
    USART_InitTypeDef USART_InitTypeDef;
    NVIC_InitTypeDef NVIC_InitTypeDef;
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA , ENABLE);    //使能USART1,GPIOA时钟
 
    //USART1_TX   GPIOA.9
    GPIO_InitTypeDef.GPIO_Pin         = GPIO_Pin_9;       //PA.9
    GPIO_InitTypeDef.GPIO_Speed       = GPIO_Speed_50MHz;
    GPIO_InitTypeDef.GPIO_Mode        = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitTypeDef);                 //初始化GPIOA.9
 
    //USART1_RX      GPIOA.10初始化
    GPIO_InitTypeDef.GPIO_Pin         = GPIO_Pin_10;           //PA10
    GPIO_InitTypeDef.GPIO_Mode        = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitTypeDef);                       //初始化GPIOA.10
 
 
    //Usart1 NVIC 配置
    NVIC_InitTypeDef.NVIC_IRQChannel                   = USART1_IRQn;
    NVIC_InitTypeDef.NVIC_IRQChannelPreemptionPriority = 3;         //抢占优先级3
    NVIC_InitTypeDef.NVIC_IRQChannelSubPriority        = 3;         //子优先级3
    NVIC_InitTypeDef.NVIC_IRQChannelCmd                = ENABLE;    //IRQ通道使能
    NVIC_Init(&NVIC_InitTypeDef);                                   //根据指定的参数初始化VIC寄存器
 
    //USART 初始化设置
 
    USART_InitTypeDef.USART_BaudRate      = bound;                          //串口波特率
    USART_InitTypeDef.USART_WordLength    = USART_WordLength_8b;            //字长为8位数据格式
    USART_InitTypeDef.USART_StopBits      = USART_StopBits_1;               //一个停止位
    USART_InitTypeDef.USART_Parity        = USART_Parity_No;                //无奇偶校验位
    USART_InitTypeDef.USART_Mode          = USART_Mode_Rx | USART_Mode_Tx;  //收发模式
    USART_InitTypeDef.USART_HardwareFlowControl    = USART_HardwareFlowControl_None; //无硬件数据流控制
 
    USART_Init(USART1, &USART_InitTypeDef);             //初始化串口1
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);      //开启串口接受中断
    USART_Cmd(USART1, ENABLE);                          //使能串口1
}

void USART1_IRQHandler(void) {//串口1中断服务程序
//   u8 Res;
//   Res = USART_ReceiveData(USART1);
     USART_SendData(USART1, (uint16_t) USART_ReceiveData(USART1));//将接收到的数据返回
}

main.c

#include <misc.h>
#include <stdio.h>
#include <stm32f10x.h>
#include "delay/delay.h" 
#include "usart/usart.h" 

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wuninitialized" 

int main(int argc, char **argv) { 

    delay_init(); 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 
    USART_INIT(115200); //串口初始化

    char* msg; 
    int i = 0; 
    while (1) 
    { 
        sprintf(msg,"你好_欢迎来到_杨海健_博客__USART1_%d\r\n",i++);
        //sprintf(msg,"TAKE_TODAY_USART1_%d\r\n",i++);
        USART_SendStr(USART1,msg); 
        delay_ms(1000); 
    } 
} 
#pragma GCC diagnostic pop

实验结果
ON Linux

Linux 测试结果

ON Windows
超级终端:

Today_20180502_200857png

串口调试助手:

串口调试助手 TODAY BLOG

以下是去掉发送的程序执行结果,电脑发送没有出错

Today_20180502_201257png

最后发送 LOGO哈哈

Today_20180502_203645png

回帖   
请输入回帖内容...