UART 驱动程序开发
1.基本概念
UART, Universal Asynchronous Reciver and Transmitter 串行异步收发器
串行通信和并行通信
串行通信传输效率低,但是硬件互联成本低.
并行通信
并行通信传输效率高,硬件互联成本高.
异步通信 同步通信的区别?
串行通信**按传输方向来定义传输**的方式
单工
任何时候数据只能朝一个方向传输
半双工
数据可以朝两个方向传输,但任何一个时刻只能朝一个方向传输
全双工
数据可以同时两个方向传输
串行接口标准:
RS232, RS422, RS485
RS232:
电气特性:
逻辑0: +3~+15V
逻辑1:- 3~-15V
机械特性:
传输距离 < 10m
RS485:
采用差分信号
传输时使用两条线
传输距离超过1000m
工业控制中使用比较多
TTL电平,计算机内部使用的
低电平 < 0.8V (0~0.8V)
高电平 > 2.4V (2.4~3.3V)
串行通信的通信协议
空闲状态下是高电平
发送数据时,数据位的个数可以是5~8位 先由低位开始发送
校验位可以采用奇校验/偶校验/无校验
通信过程中的几个重要的参数
数据位:5~8位
校验:奇/偶/无校验
停止位:1~2位
波特率: bps (bit per second)
2.电路原理图
PC_RXD1------>UARTRXD0------>GPIOD14
PC_TXD1------------------------------>GPIOD18
实现UART通信时序有两种方式:
1) 软件直接控制GPIO管脚 (纯软件模拟的方式)
2) 软件控制UART控制器,uart 控制器控制GPIO管脚.(软硬件结合)
问题:uart 控制器可以做哪些工作
还需要软件完成哪些工作,以及如何配合工作.
3.Cpu data sheet uart章节
AE19(GPIOD14) :功能1(UARTRXD0)
AD19(GPIOD18):功能1(UARTTXD1)
串口线和CPU内部的哪个uart控制器相关.--->根据COM1连接的CPU管脚位GPIOD14.GPIOD18.
这两个管脚有UARTTXD0和UARTRXD0 ---->推断和uart0控制器相连.
CPU感知外部硬件的变化的方式:
1).轮讯
2).中断
3).DMA
UART相关的控制器
ULCON控制器
配置: 8N1 115200 non-fifo 轮询模式
8: 8个数据位
N: 无奇偶校验
1:1位停止位
115200: bps
ulcon0 基址: 0xc00a1000
[1:0] 11,数据位个数
[2] 0,1个停止位
[5:3] 000,无校验
[6] 0,非红外模式
ucon0 基址: 0xc00a1004
[1:0] 01,接收采用轮询模式
[3:2] 01,发送在用轮询模式
[4] 0,不发送打断信号
[5] 0,非回环模式
uartstat0 基址: 0xc00a1010
[0] 0/1接收缓冲区中有无有效数据
[1] 0/1 发送缓冲区非空/空
[2] 1.发送缓冲区为空 并且发送移位寄存器也为空
utxh0 基址: 0xc00a1020
[7:0] 要发送的数据写入其中
urth0 基址: 0xc00a1024
[7:0] 读取接受到的寄存器
UART0CLKENB 基址: 0xc00A9000
[2] 0/1 禁止/使能 uart0控制器的时钟.
UART0CLKGEN0L 基址: 0xc00A9000
[4:2] uart0时钟源的选择 ---> 010--->选择PLL1作为uart0的时钟源
[12:5] 15, PLL1 =800mHz. (第一次分频) 800/(15+1) = 50MHz
UBRDIV0 <---- (50000000 / (115200 * 16) ) - 1 = 27.13 - 1 = 26
UFRACVAL0 <---- 0.13*16 = 2
main.c
#include "uart.h"
#include "led.h"
#include "cmd.h"
#define CMD_MAX_LEN (32)
unsigned char cmd_buf[CMD_MAX_LEN]; //在板子外扩的ram里分
int main (void)
{
_cmd *pdata = (_cmd *)0;
/*8N1 115200 polling non-fifo*/
uart_init ();
/*选择GPIO功能1*/
led_init ();
while (1) {
//uart_puts ("\n hello world!\n");
/*输出命令提示符*/
uart_puts ("\n liuyang# ");
/*接受用户输入的字符*/
uart_gets(cmd_buf, CMD_MAX_LEN);
/*匹配用户输入的命令*/
#if 0
if (my_strcmp (cmd_buf, "led1on")== 0) {
led1on();
}
if (my_strcmp (cmd_buf, "led1off")== 0) {
led1off();
}
#endif
pdata = find_cmd (cmdbuf);
/*执行命令对应的硬件操作*/
if (pdata)
{
pdata->func();