ARM⑤——串行通信
ARM⑤——串行通信
一、设备间通信实现
传输流程
起始位——>数据位——>校验位——>停止位 , 发送完成——>空闲状态
传输速率——波特率一致
二、UART串口通信
1、串口核心器件
- 发送器(TX):负责将 CPU 输出的并行数据(如 8 位二进制数)转换成串行数据(逐位传输),并添加通信协议所需的 “起始位、停止位、校验位”。
- 接收器(RX):负责从外部接收串行数据,逐位解析后转换成并行数据,同时校验数据正确性(如校验位、停止位检测)。
- 波特率发生器:生成稳定的时钟信号,用于同步发送 / 接收的 “位传输速度”(即波特率,需与通信对方一致)。
2、通信协议规定
UART 是 “异步通信”,无时钟线同步,因此通信双方必须预先约定 4 个核心参数,否则数据会解析错误:
- 波特率:每秒传输的 “比特数”(如 9600bps、115200bps),决定数据传输速度,双方波特率需完全一致(波特率发生器需生成对应时钟)。
- 数据位:每帧数据中 “有效数据的位数”(常用 8 位,少数场景用 5/6/7/9 位),如 8 位时,每次传输 1 个字节的有效数据。
- 停止位:每帧数据末尾的 “结束标志”,用于告知接收器 “当前帧已结束”,可配置为 1 位、1.5 位或 2 位(常用 1 位)。
- 校验位(可选):用于检测数据传输错误,分为奇校验(数据位 + 校验位的 “1” 的总数为奇数)、偶校验(总数为偶数)、无校验(不添加校验位),双方校验规则需一致。
3、ARM内的具体使用流程
外设原理图查找
UART——>CON7——>BUF_XuTXD2——>XuTXD2/UART_AUDIO_TXD 发送端
——>BUF_XuRXD2——>XuRXD2/UART_AUDIO_RXD 接收端
核心原理图查找
XuTXD2/UART_AUDIO_TXD——> XuTXD2 / UART_AUDIO_TXD/GPA1_1 发送
XuTXD2/UART_AUDIO_RXT——> XuTXD2 / UART_AUDIO_TXD/GPA1_0 接收
芯片手册
使能
寄存器 地址 Bit 值 备注 GPA1CON 0x11400020 [7:4] 0x2 = UART_2_TXD 使能串口2输出 [3:0] 0x2 = UART_2_RXD 使能串口2接收 设置
寄存器 地址 bit 值 备注 ULCON2 0x13820000 [1:0] 11 传输位=8位 [2] 0 1位终止位 [5,3] 000 无校验 [6] 0 普通模式 UCON2 0x13820004 [3:2] 01 传输模式:中断、轮询 [1:0] 01 接收模式:中断、轮询 UTRSTATn 0x13820010 [1] 1 or 0 写缓存可用时 该bit位为1 [0] 1 or 0 读缓存就绪,该bit为1 分频计算及初始化
For example, if the Baud rate is 115200 bps and SCLK_UART is 100 MHz, UBRDIVn and UFRACVALn are: DIV_VAL = (100000000/(115200 16))–1 = 54.25 – 1 = 53.25 UBRDIVn = 53 (integer part of DIV_VAL) UFRACVALn/16 = 0.25 = 4/16 Therefore, UFRACVALn = 4当波特率为115200的时候,串口时钟频率为100MHz ,UBRDIVn 和 UFRACVALn寄存器的公式如上计算。
UBRDIVn ——整数部分
UFRACVALn——小数部分
- 代码部分
#define GPA1CON (*(volatile unsigned int *)0x11000020) #define ULCON2 (*(volatile unsigned int *)0x13820000) #define UCON2 (*(volatile unsigned int *)0x13820004) #define UBRDIV2 (*(volatile unsigned int *)0x13820028) #define UFRACVAL2 (*(volatile unsigned int *)0x1382002C) #define UTXH2 (*(volatile unsigned int *)0x13820020) #define URXH2 (*(volatile unsigned int *)0x13820024) #define UTRSTAT2 (*(volatile unsigned int *)0x13820010) //延时函数 void delay(int n) { volatile int cnt = 0; while(n--) { for(cnt ; cnt < 1024 ; cnt++) {} } } void int_to_string(int num, char *str) { int i = 0; // 字符串索引 int is_negative = 0; // 标记是否为负数 unsigned int n; // 用无符号数处理绝对值(避免-2147483648溢出) // 处理负数 if (num < 0) { is_negative = 1; n = (unsigned int)(-num); // 转为无符号数避免溢出 } else { n = (unsigned int)num; } // 特殊情况:数字为0 if (n == 0) { str[i++] = '0'; } else { // 提取每一位数字(逆序存储)——原本就是while循环,无需修改 while (n > 0) { str[i++] = (n % 10) + '0'; // 数字转ASCII字符 n /= 10; } } // 添加负号(若为负数) if (is_negative) { str[i++] = '-'; } // 反转字符串(用while循环替代for循环) int j = 0; // 初始化左指针 int half_len = i / 2; // 计算需要交换的次数 while (j < half_len) { // 交换对称位置的字符 char temp = str[j]; str[j] = str[i - 1 - j]; str[i - 1 - j] = temp; j++; // 移动左指针 } str[i] = '\0'; // 添加字符串终止符 } //初始化 串口2 void uart_init() { //GPA1使能 UART_2_TX GPA1CON = (GPA1CON & (~(0xff << 8))) | (0x22 << 8); //ULCON2 数据位 = 8 stop = 0 , 无校验 普通模式 ULCON2 = (ULCON2 & (~(0x7f << 0))) | (0x3 << 0); //UCON2 UCON2 = (UCON2 & (~(0xf << 0))) | (0x5 << 0); //UBRDIV2 分频 这里直接等于是因为其余位都是保留 UBRDIV2 = 53; UFRACVAL2 = 4; } //发送单字节数据 void uart_sendChar(char ch) { //判断数据发送 buffer是否为空 while((UTRSTAT2 & (0x2)) == 0); UTXH2 = ch; } //发送字符串 void uart_sendStr(char *str) { while(*str != '\0') { uart_sendChar(*str); str++; } } void uart_sendInteger(int num) { //缓冲区 char buf[13] = {0}; int_to_string(num,buf); uart_sendStr(buf); } //接收字符 char uart_getChar() { while((UTRSTAT2 & (0x1)) == 0); return (URXH2 & 0xff); } void main() { char *str = "hello world!"; int num = 5000; uart_init(); uart_sendStr(str); //delay(1024); uart_sendInteger(num); while(1) { } }
