1.0 GD 32 串口通信基础知识
串行通信与并行通信
第一个是并行通信的原理图,第二个是串行通信的原理图,并行通信表示多个通道同时发送和接收数据,串行通信表示只有一条数据线,数据是从数据线上一位一位的发送。
常见的通信协议主要有IIC,USART,SPI,CAN总线【CAN是一种差分数据线】
同步通信和异步通信的概念:同步指的是通信双方约定特定的时钟传输频率,这个频率是比较严格的,通信双发必须严格的按照这个频率进行数据传输。
异步通信:通信双方有自己的数据线和时钟线无需约定特定的通信频率进行数据的传输,但是需要按照协议的规定进行数据的传输和发送。
比如:串口通信就是开始时高电平,当出现低电平的时候就是告诉单片机我要开始数据的发送了,之后通过电平的高低起伏一个bit一个bit的将数据发送出去,其中还可以再发送字节的后面添加一个校验问,如CRC校验,奇偶校验等,结束时将电平拉高,方便后续字节的发送。
串口有一个发送数据叫TXD 主要是用于数据的发送,有一个RXD主要是用于数据的接收,对应上面数据发送和接收的过程。
2.0 单工,双工,半双工的概念
知道了解这个概念很多地方都会讲到,以下直接贴图的方式进行展示
3.0 串口的几种常见的电器协议
第一种是TTL电平,3.3V或者5V表示高电平,0V表示低电平,TTL电平适合用于短距离的通信
以上是RS232电平 -3~-15表示高电平,3 ~ 15V 表示低电平0,最大的通信距离是15m
4.0 ARM 单片机硬件结构讲解
5.0 单片机串口的硬件结构
串口的波特率需要按自己的实际使用情况进行选择,51单片机串口的波特率需要自己计算
目前我使用的这款单片机串口的复用使用情况
6.0 串口通信的差错校验方式
这种检验方式需要自己进一步的学习,后续会补充到
7.0 串口通信实验
注:复位串口的作用是将串口的状态恢复成初始值,方便后面对串口进行配置
在初始化串口之前,通常会先复位它以确保所有的设置都回到初始状态,然后进行新的配置。所以,正确的初始化序列通常会包括先复位串口,使能时钟,然后配置串口参数(如波特率、数据位数、停止位数等),最后可能还需要使能接收和发送功能。
直接按照上面的示例步骤进行配置即可,以下是程序的结构
USART.C文件代码
#include "gd32f30x.h" // Device header
#include <stdint.h>
#include <stdio.h>typedef struct{uint32_t uartNo;rcu_periph_enum rcuUsart;rcu_periph_enum rcuGpio;uint32_t gpio;uint32_t txPin;uint32_t rxPin;
}UartHwInfo_t;// 结构体数组存放成员变量的值
static UartHwInfo_t g_uartHwInfo = {USART0,RCU_USART0,RCU_GPIOA,GPIOA,GPIO_PIN_9,GPIO_PIN_10}; static void Usb2ComGpioInit(void){rcu_periph_clock_enable(g_uartHwInfo.rcuGpio);gpio_init(g_uartHwInfo.gpio,GPIO_MODE_AF_PP,GPIO_OSPEED_10MHZ,g_uartHwInfo.txPin);gpio_init(g_uartHwInfo.gpio,GPIO_MODE_IPU,GPIO_OSPEED_10MHZ,g_uartHwInfo.rxPin);}static void UsbComUsartInit(uint32_t baudRate){/*使能串口时钟 */rcu_periph_clock_enable(g_uartHwInfo.rcuUsart);// 复位串口usart_deinit(g_uartHwInfo.uartNo);// 通过串口USART_CTL设置WL的字符串长度usart_word_length_set(g_uartHwInfo.uartNo,USART_WL_8BIT);// 设置串口的校验位,设置没有校验位usart_parity_config(g_uartHwInfo.uartNo,USART_PM_NONE);// 设置串口停止位的长度usart_stop_bit_set(USART0,USART_STB_1BIT);// 设置波特率usart_baudrate_set(g_uartHwInfo.uartNo,baudRate);// 发送使能,也就是使能串口数据发送usart_transmit_config(g_uartHwInfo.uartNo, USART_TRANSMIT_ENABLE);// 使能串口的数据接收usart_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_ENABLE);// 使能串口接收中断usart_interrupt_enable(g_uartHwInfo.uartNo, USART_INT_RBNE);// 使能串口中断嵌套中断向量控制器,第二个是抢占式优先级,后面那个是响应式优先级nvic_irq_enable(USART0_IRQn, 0, 0);//使能UART,只有使能串口后数据才有用usart_enable(g_uartHwInfo.uartNo);
}void Usb2ComTest(){// 每次移动数据,也就是移位寄存器的时间for(uint8_t i = 0; i <= 250; i++){// 将数据一个个的发送出去usart_data_transmit(g_uartHwInfo.uartNo,USART_FLAG_TBE);// 当移位数据寄存器的值为1的时候表示数据可以发送,0的时候表示还不能程序会一直卡在这个位置while(RESET == usart_flag_get(g_uartHwInfo.uartNo,USART_FLAG_TBE));}// 获取状态寄存器标志位while(RESET == usart_flag_get(g_uartHwInfo.uartNo,USART_FLAG_TC));// 关闭串口发送的功能,数据寄存器里面的数据是空的,但是移位寄存器里面的数据不一定是空的usart_transmit_config(g_uartHwInfo.uartNo, USART_TRANSMIT_DISABLE);
}
/*硬件初始化串口
*/
void Usb2ComDrvInit(void){// GPIO 初始化Usb2ComGpioInit();// 串口初始化UsbComUsartInit(115200);}
/*打印输出程序,pritf函数默认打印输出到显示器如果需要输出到串口,必须重新实现fputc函数,将输出指向串口,称之为重定向
*/
int fputc(int ch,FILE *f){usart_data_transmit(g_uartHwInfo.uartNo, (uint8_t)ch);while (RESET == usart_flag_get(g_uartHwInfo.uartNo, USART_FLAG_TBE));return ch;
}
USART.H文件代码
#ifndef __USART_H_
#define __USART_H_void Usb2ComDrvInit(void);
void Usb2ComTest();#endif
MAIN.C文件
#include <stdio.h>
#include "gd32f30x.h"
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "USART.h"
#include <stdio.h>int main(void)
{ // 初始化LEDLED_Init();KeyDrvInit();// 串口初始化接口函数Usb2ComDrvInit();// 串口测试程序Usb2ComTest();printf("This is UART printf test!\n"); // 打印到显示器里面,并不是打印到串口while(1){} }
8.0 程序发送数据运行结果
9.0 fpuchar函数重定向
使用这个函数默认是打印在显示器上的,要是想要这个数据在串口上打印输出需要对这个函数进行从定向fput()函数。
/*打印输出程序,pritf函数默认打印输出到显示器如果需要输出到串口,必须重新实现fputc函数,将输出指向串口,称之为重定向
*/
int fputc(int ch,FILE *f){usart_data_transmit(g_uartHwInfo.uartNo, (uint8_t)ch);while (RESET == usart_flag_get(g_uartHwInfo.uartNo, USART_FLAG_TBE));return ch;
}
9.0 补充标志位参数知识
例如:
/* get flag USART0 state */
FlagStatus status;
status = usart_flag_get(USART0,USART_FLAG_TBE);
以上知识基于本人学习总结与理解,仅用于学习参考,参考郭天祥老师教学视频与文档撰写
。。。