注:以下内容学习于韦东山老师arm裸机第一期视频教程
一.uart(Universal ASynchronous Receiver and Transmitter)简介
1.1 串口的作用
1.1.1 打印调试信息
1.1.2 外接各种模块,例如GPS,蓝牙等
1.2 串口使用
1.2.1 设置波特率
1.2.2 数据格式(数据位,停止位,校验位,流控)
1.3 串口协议
假设ARM要发送一个字节给电脑,例如一个字符'A' = 0x41,对应2进制 0100 0001
1.3.1 双方先约定好每一位占据的时间(波特率),假设为1s
1.3.2 首先arm将TXD引脚拉低,维持1bit(1s)时间
1.3.3 PC机载低电平开始处计时
1.3.4 arm根据数据驱动引脚TXD电平,每一位维持1bit(1s)时间,发送8位,称为数据位
PC机在数据位的中间读取引脚状态
1.3.5 第7位发送完成之后,发送校验位(奇偶校验位,数据位+校验位中为1的个数是奇数或者偶数)
校验位现在基本用不到了,电子技术很稳定
1.3.6 最后发出停止位,高电平(可以约定停止位占据的时间)
1.4 逻辑电平
这些电平对应为逻辑电平,即1,0分别对应多少V,有很多种逻辑电平。
例如TTL/CMOS逻辑电平,12V-3V表示0,-3V-12V表示1,不适合长距离传输
引入RS232电平适合长距离传输。
开发板上的电平是TTL电平,电脑上是RS232电平,如果要想连接需要引入电平转换芯片,将TTL电平转换为RS232电平(mini2440)
对于JZ2440没有使用电平转换芯片,因为很多电脑没有使用串口,串口0直接接usb串口芯片连接电脑.
串口1,串口2仍然保持TTL电平
二.2440串口结构
2.1 2440串口结构图如下:
2.2 串口发送
对于2440,我们需要将数据从内存中取出通过串口控制器发送出去,在串口线上我们是逐位发送的。
2.2.1 因此肯定会有一个移位器对应图的Transmit Shifter
2.2.2 移位的数据来自于fifo,图中的Transmit Buffer Register,
2.2.3 而fifo中的数据来自于内存。
2.3 串口接受
在串口线上接受数据也是逐位接受的
2.3.1 移位器逐位接受数据
2.3.2 放入fifo
2.3.3 程序从fifo中取出数据
2.4 问题-> 如何知道数据/接受发送完毕?
2.4.1 中断CPU
2.4.2 查询状态
三.Uart编程(具体参考程序代码注释)
3.1 串口初始化
3.1.1 配置引脚
a.配置GPHCON寄存器,配置串口0的TXD,RXD引脚
b.配置GPHUP寄存器,TXD,RXD上拉,因为起始位是通过拉低电平来表示的
3.1.2 设置波特率
在2440芯片手册上有如下公式:
我们需要设置UBRDIVn来控制串口的时钟分频得到波特率
3.1.3 设置数据格式(8n1)
3.2 输出函数
3.3 接受字符函数
代码如下:
#include "uart.h"
/* 115200,8n1 */
void Uart0Init()
{
/* 1.配置引脚 */
/* 1.1 配置GPH2,GPH3用作TXD,RXD */
GPHCON &= ~((0X3 << 2*2) | (0X3 << 2*3));
/* 1.2 配置GPH2,GPH3内部上拉 */
GPHUP &= ~((0x1 <<2) | (0x1 << 3));
/* 2.设置波特率115200 */
/*
* 2.1 设置UART clock
* UCON0 bit[11:10] = 0, UART clock = PCLK = 50M
* UCON0 bit[1:0] = 1, 中断/轮询模式接受
* UCON0 bit[3:2] = 1, 中断/轮询模式发送
*/
UCON0 = 0x5;
/* 2.2 设置分频系数UBRDIVn
* UBRDIVn = (int)(UART clock / (baud * 16)) - 1
* = (int)(PCLK / (115200 * 16)) - 1
* = (int)(50000000 / (115200 * 16)) - 1 = 26;
*/
UBRDIV0 = 26;
/* 3.设置数据格式 */
ULCON0 = 0x3; /* 8n1 */
}
void putchar(char c)
{
while (!(UTRSTAT0 & (1 << 1)));
UTXH0 = c;
}
int getchar()
{
while (!(UTRSTAT0 & (1 << 0)));
return URXH0;
}
void puts(const char *s)
{
while (*s)
{
putchar(*s);
s++;
}
}
测试代码如下:
#include "uart.h"
int main()
{
char c;
Uart0Init();
puts("Hello, World!\n");
while (1)
{
c = getchar();
if(c == '\n')
putchar('\r');
if(c == '\r')
putchar('\n');
putchar(c); /* 回显输入语句 */
}
return 0;
}