单片机学习小组
直播中

丁冬芹

7年用户 1268经验值
私信 关注

处理器与外部设备通信有哪几种方式?

处理器与外部设备通信有哪几种方式?
串口配置过程是怎样的?


回帖(1)

李伟嘉

2022-2-28 14:49:59
正篇


1.处理器与外部设备通信的两种方式:
并行通信:

-传输原理:数据的各个位同时传输
-优点:速度快
-缺点:占用引脚资源多

串行通信:
-传输原理:一位一位地传输数据
-优点:占用资源较少
-缺点:速度慢

串口通信按照传输的方向可以分为:单工,半双工和全双工。
单工:只能一个方向上进行传输
半双工:允许双向通信,但是同一时间只能是单一方向传输。(类似于两个时间切换方向的单工)
全双工:允许同时间的双向通信。

串口的通信方式可分为:同步和异步通信。
同步通信:带有时钟线的通信方式。
异步通信:不带有时钟线的通信方式。
STM32F103系列单片机共有5个串口,其中1-3是 通用同步/异步串行接口 USART,4、5是 通用异步 串行接口 UART。


(图片来源正点原子B站教程)

(图片来源正点原子B站教程)

对于传输的数据,我们需要一些参数。
1.起始位 2. 数据位(可设置8位或者9位) 3.奇偶校验位 4.停止位 5.波特率(因为是异步通信所以要提前设置好波特率,同样对于通信的对象,也要提前设置好波特率并且要和单片机的波特率相同才能正常通信)
最重要的就是波特率的设置,能够成功通信的前提就是有合适统一的波特率。

波特率的计算公式:
(波特率的产生原理与相关寄存器配置相当麻烦,这里不再说明。只要掌握计算与相应库函数参数配置就可以。)

串口配置过程




了解了串口通信的一些基础知识之后,就要掌握STM32的串口配置过程。前面省略了一些相关寄存器说明,这里会简要说明一下。


我们通过库函数主要配置以下几个寄存器:
状态寄存器(USART_SR)
数据寄存器(USART_DR)
波特比率寄存器(USART_BRR)
控制寄存器 x(USART_CRx)
(具体功能不再细说。)

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



  • 串口时钟使能,GPIO 时钟使能 RCC_APB2PeriphClockCmd()
  • 串口复位 (这一步不是必须)void USART_DeInit();
  • GPIO 端口模式设置 GPIO_Init(); GPIO_Mode 设置为复用推挽输出
  • 串口参数初始化
    {
    void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
    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); //初始化串口
    }
  • 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
  • 使能串口 USART_Cmd();
  • 编写中断处理函数 void USART1_IRQHandler()可以在“stm32f0x.h”这个头文件找到。


串口数据的接收和发送:从DR寄存器里读取和写入数据。
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

#include "stm32f10x.h"

void Usart1_Init()
{
        //GPIO口初始化参数结构体
        GPIO_InitTypeDef GPIO_InitStructure;
        // 串口初始化参数结构体
        USART_InitTypeDef USART_InitStructure;
        //中断初始化参数结构体
        NVIC_InitTypeDef NVIC_InitStructure;
        //使能GPIOA
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        //使能USART  1
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
      
        //设置GPIOA9 为 复用推挽输出 速度为10MHz(PA9 复用为串口发送引脚)
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
      
        //初始化GPIOA9
        GPIO_Init(GPIOA, &GPIO_InitStructure);
      
        //设置GPIO10 为 浮空输出 速度为10MHz(PA10 复用为串口接收引脚)
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
        //初始化GPIOA10
        GPIO_Init(GPIOA, &GPIO_InitStructure);
      
        //串口初始化参数
        //设置波特率为115200
        USART_InitStructure.USART_BaudRate = 115200;
        //不启用硬件流控制
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        //设置为串口收发模式
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        //无奇偶校检位
        USART_InitStructure.USART_Parity = USART_Parity_No;
        //一个停止位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        //设置数据帧长为 8位
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        //初始化串口
        USART_Init(USART1, &USART_InitStructure);
        //使能串口
        USART_Cmd(USART1, ENABLE);
        //开启串口接收中断
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
      
        //串口1通道
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        //使能中断
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        //设置抢占优先级
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        //设置响应优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      
        //初始化中断优先级
        NVIC_Init(&NVIC_InitStructure);
}

/*串口接收中断服务函数*/
void USART1_IRQHandler()
{
        //定义接收数据变量
        unsigned char res;
        //判断串口接收中断是否发生
        if(USART_GetITStatus(USART1, USART_IT_RXNE))
        {
                //接收数据
                res = USART_ReceiveData(USART1);
                //发送刚接收的数据
                USART_SendData(USART1, res);
        }
}

int main()
{
        //串口初始化
        Usart1_Init();
        //中断分组
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        while(1);
}



结语:


简单的串口知识与配置已经记录完了,后续可能会有深度详细的补充。
若有错误,还请评论指出。
共同进步。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分