串口问题

时间:2024-02-25 12:55:05

串口数据发送与接收问题

配置好串口,无法打印问题

问题原因:没有勾选 “微库”

解决方法:勾选微库,重新编译,下载;

image-20201223091612582

串口打印数据不正确

波特率错误:

  1. 检查单片机的时钟配置是否正确

    外部晶振时钟大小;倍频后是否是72MHz;

  2. 使用寄存器时,波特率计算错误;

串口波特率计算问题

  • 寄存器配置的时候,波特率的计算

    计算公式与方法:

    image-20201223153706694

    image-20201223153811536

\[USARTDIV = Fclk/ (16 * 波特率) \]

image-20201223154039883

算法1:

根据公式,算出USARTDIV

取分频值的整数部分:Mantissa

取分频值的小数部分:Fraction;向上取整;

将两个数合并,放入寄存器中;

u16 Mantissa = 0;
u16 Fraction = 0;
float USARTDIV = 0;	
USARTDIV = 72000000.0/16/brr;
Mantissa = (u16)USARTDIV;
Fraction = (u16)((USARTDIV - Mantissa)*16 + 0.5);
USART1->BRR = Mantissa<<4 | Fraction;	//将值放入寄存器中

算法2:

小数的 二进制 存储形式:

​ 如:19.625 19:10011 0.625 = 0.625 = 1*2-1 + 0*2-2 + 1*2-3 = 101

  • 0.625 * 2 = 1.250 取整 1

    0.250 * 2 = 0.5 取整0

    0.5 * 2 = 1.0 取整1

    0.0 * 2 = 0

所以说:9600

​ 需要的 USARTDIV = 72000000 / (16 * BRR) = 468.75

​ 对应的二进制存储形式:1 1101 0100.11

与 寄存器(USART1->BRR)的值 就差 左移4位;

1 1101 0100.11 << 4 = 0001 1101 0100 1100(位数不够就补0)

所以 USART1->BRR = USARTDIV * 16 = 72000000 / (16 * BRR) *16 = 72000000.0/BRR

USART1->BRR = 72000000.0/brr;
//是因为二进制的存储格式导致的;

串口使用printf

方法:编写 fputc 函数

  1. 包含头文件 #include ”stdio.h“
  2. 编写 fputc 函数

image-20201223155708466

编写 fputc 函数

  • printf 是如何工作的

    printf(“1234”); 输出到屏幕的时候,是调用 fputc 将字符一个 一个 输出到屏幕上;

    ​ 就等于 fputc(‘1’); fputc(‘2’); fputc(‘3’); fputc(‘4’);

    所以想要将数据 输出到 串口助手:只需要将 字符 利用 串口 发送出去;

  • 根据函数声明格式,写出函数原型

    image-20201223160037213
  • 函数编写,就是将数据 从串口发送出去;

    fputc 需要有一个返回值,就返回 c;

    image-20201223160531672

printf函数的使用

printf 是格式化 控制输出到 设备上;

在这的 printf 是将 数据 输出到串口(助手)上;

串口助手数据的发送与接收

通过串口,每次发送和接收的数据都是8位;

如果发送16进制的数,要发送两个,一个16进制是4个位;

数据接收

数据接收 显示形式

​ 数据的内容不变,只是数据的显示方式改变;

  1. 字符型显示

    通过 串口 发送过来的 数据;都是二进制的0和1;

    数据可以输是字符型数据,可以是整数;(数据本身是0和1)

    在串口助手中 会将数据的形式 以字符型数据显示

    如果说发送的数据是 整数65;串口助手以字符型的方式显示为 A

  2. 16进制显示

    从串口发送过来的数据,将数据的显示方式改为16进制;

    如果发送的是 字符 ‘A’,对应的整数是 ”65“;对应的16进制数为 ”41“(串口助手16进制显示)

数据发送

数据的发送形式:

  1. 字符型

    1个字符型数据 是 8位,每次发送数据是一个字符一个字符发送的;

    字符发送的时候,MCU接收到的数据是 对应字符的二进制数;

    整数1 != 字符型数据 ‘1’,比较的时候,要格外注意数据的格式

  2. 16进制

    发送16进制的数据 每次要发送 2个,如果发送的数据不够,MCU的接收中断不会触发;

    如果发送的数据太多,MCU每次接收2个字节的数据,要保证数据能够不丢失;