历史上的今天
今天是:2024年12月22日(星期日)
2021年12月22日 | Tiny4412之串口(Uart)驱动编写
2021-12-22 来源:eefocus
一:tiny4412串口驱动编写
1、串口通信简介
串口通信指串口按位(bit)发送和接收字节,串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线 接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2 米;而对于串口而言,长度可达1200米。
串口通信所采用的通信协议为RS-232,RS-232通信方式允许简单连接三线:Tx、Rx和地线。但是对于数据传输,双方必须对数据定时采用使用相同的波特率。RS-232(ANSI/EIA-232标准)是IBM-PC及其兼容机上的串行连接标准。可用于许多用途,比如连接鼠标、打印机或者Modem,同时也 可以接工业仪器仪表。用于驱动和连线的改进,实际应用中RS-232的传输长度或者速度常常超过标准的值。RS-232只限于PC串口和设备间点对点的通信。
2、串口的通信基本模型如下图所示:

TXD:发送数据
RXD:接收数据
GND:地线
串口驱动跟其他外设的驱动配置流程差不多,大概分为如下几步:
(1)查看电路图,配置相应的gpio功能引脚
(2)配置串口控制器的相应寄存器
(3)测试串口接收、发送
今天用的是第一个串口com0,下面是电路图:

找到相应的gpio功能引脚

下面是串口工作的整个模式图:

下面是串口控制器相应的寄存器:

今天我们实验用到的几个主要的寄存器是:
ULCON0:数据格式控制寄存器(配置数据位,停止位,校验位等);
UCON0:串口控制开关
UTXH0:发送数据
URXH0:接收数据
UTRSTAT0:数据收发状态寄存器
UBRDIV0,UFRACVAL0:配置波特率的
下面是uart所需要的工作得时钟频率,以及比特率计算公式:


经过计算uart所采用的SCLK_UART为100M
UBRDIV0=(100000000)/(115200 x16) - 1 = 53.3=53=0x35;
UFRACVAL0= 4;
下面具体测试代码:
1 #ifndef __REGS_H
2 #define __REGS_H
3
4 #define gpa0base 0x11400000
5 #define GPA0CON (*(volatile unsigned long *)(gpa0base + 0x0000))
6
7 #define uart0base 0x13800000
8 #define ULCON0 (*(volatile unsigned long *)(uart0base + 0x0000))
9 #define UCON0 (*(volatile unsigned long *)(uart0base + 0x0004))
10 #define UFCON0 (*(volatile unsigned long *)(uart0base + 0x0008))
11 #define UMCON0 (*(volatile unsigned long *)(uart0base + 0x000C))
12 #define UTRSTAT0 (*(volatile unsigned long *)(uart0base + 0x0010))
13 #define UERSTAT0 (*(volatile unsigned long *)(uart0base + 0x0014))
14 #define UFSTAT0 (*(volatile unsigned long *)(uart0base + 0x0018))
15 #define UMSTAT0 (*(volatile unsigned long *)(uart0base + 0x001C))
16 #define UTXH0 (*(volatile unsigned char *)(uart0base + 0x0020))
17 #define URXH0 (*(volatile unsigned char *)(uart0base + 0x0024))
18 #define UBRDIV0 (*(volatile unsigned long *)(uart0base + 0x0028))
19 #define UFRACVAL0 (*(volatile unsigned long *)(uart0base + 0x002C))
20 #define UINTP0 (*(volatile unsigned long *)(uart0base + 0x0030))
21 #define UINTSP0 (*(volatile unsigned long *)(uart0base + 0x0034))
22 #define UINTM0 (*(volatile unsigned long *)(uart0base + 0x0038))
23
24 #define uart3base 0x13830000
25 #define ULCON3 (*(volatile unsigned long *)(uart3base + 0x0000))
26 #define UCON3 (*(volatile unsigned long *)(uart3base + 0x0004))
27 #define UFCON3 (*(volatile unsigned long *)(uart3base + 0x0008))
28 #define UMCON3 (*(volatile unsigned long *)(uart3base + 0x000C))
29 #define UTRSTAT3 (*(volatile unsigned long *)(uart3base + 0x0010))
30 #define UERSTAT3 (*(volatile unsigned long *)(uart3base + 0x0014))
31 #define UFSTAT3 (*(volatile unsigned long *)(uart3base + 0x0018))
32 #define UMSTAT3 (*(volatile unsigned long *)(uart3base + 0x001C))
33 #define UTXH3 (*(volatile unsigned char *)(uart3base + 0x0020))
34 #define URXH3 (*(volatile unsigned char *)(uart3base + 0x0024))
35 #define UBRDIV3 (*(volatile unsigned long *)(uart3base + 0x0028))
36 #define UFRACVAL3 (*(volatile unsigned long *)(uart3base + 0x002C))
37 #define UINTP3 (*(volatile unsigned long *)(uart3base + 0x0030))
38 #define UINTSP3 (*(volatile unsigned long *)(uart3base + 0x0034))
39 #define UINTM3 (*(volatile unsigned long *)(uart3base + 0x0038))
40
41 #endif //__REGS_H
1 #ifndef __UART_H
2 #define __UART_H
3
4 void uart_init();
5 void set_gpio();
6 void show_serial();
7 void myputc(unsigned char c);
8 unsigned char mygetc(void);
9 void myputs(unsigned char *str);
10 void mygets(unsigned char *str);
11
12 #endif //__UART_H
1 #include "regs.h"
2 #include "uart.h"
3
4 int main()
5 {
6 set_gpio();
7 uart_init();
8 show_serial();
9 return 0;
10 }
11
12 void show_serial()
13 {
14 /*循环进行数据收发*/
15 unsigned char cmd[512];
16 while(1) {
17 myputs("[root@dream]#");
18 mygets(cmd);
19 myputs(cmd);
20 myputs("n");
21 }
22
23 }
24
25 void myputc(unsigned char c)
26 {
27 while(!(UTRSTAT0 & (1 << 1)));//等待buffer为空,再发送字符
28 UTXH0 = c;
29 }
30 unsigned char mygetc(void)
31 {
32 unsigned char ch;
33 while(!(UTRSTAT0 & 1));//等待buffer不为空
34 ch = URXH0;
35
36 return ch;
37 }
38
39 void myputs(unsigned char *str)
40 {
41 while(*str) {
42 myputc(*str);
43 if(*str == 'n')
44 myputc('r');
45 str++;
46 }
47 }
48
49 void mygets(unsigned char *str)
50 {
51 unsigned char ch;
52 while(1) {
53 ch = mygetc();//获取字符
54 myputc(ch);
55 if(ch == 'r') {
56 myputc('n');
57 break;
58 }
59 *str = ch;
60 str++;
61 }
62 *str = 0;
63 }
64
65 void set_gpio()
66 {
67 /*0x2 = UART_0_RXD
68 *0x2 = UART_0_TXD*/
69 GPA0CON &= ~0xff;
70 GPA0CON |= 0x22;
71 }
72
73 void uart_init()
74 {
75 /*step 1:数据格式控制*/
76 ULCON0 = 3; /*8bit data 1bit stop no parity*/
77 /*step 2: uart 开关*/
78 UCON0 = 1 | (1 << 2);
79 /*step 3: set Baud-rate*/
80 UBRDIV0 = 0x35;
81 UFRACVAL0 = 0x4;
82 /*step 4: 数据收发缓存*/
83 //UTXH0
84 //URXH0
85 /*step 5:数据收发状态寄存器*/
86 //UTRSTAT0
87 }
下一篇:Tiny4412之重力感应器驱动
史海拾趣
|
首先,我来说说! 1.清华大学出版社 << 8051单片机实践与应用>> 2.科学出版社 <<OP放大电路设计>> <<晶体管电路设计>> 3.北京航空航天大学出版 <<AVR单片机嵌入式 ...… 查看全部问答> |
|
为这个行业即将毕业的同学们写的一些个人简单的想法。 1、现在是很好的年代(过去的5年和未来的5年) 我们很幸运,在现在这个年代在这个专业方向开始自己的职业生涯。从过去的20年到未来的20年 ...… 查看全部问答> |
|
2-1-1.开关变压器的工作原理 开关变压器一般都是工作于开关状态;当输入电压为直流脉冲电压时,称为单极性脉冲输入,如单激式变压器开关电源;当输入电压为交流脉冲电压时,称为双极性脉冲输入,如双激式变压器开关电源;因此,开关变压器也可以 ...… 查看全部问答> |
|
WaitForMultipleObjects返回WAIT_FAILED的问题 情况如下: 设置了一个全局变量HANDLE g_hevInt[3]; 在程序里创建了三个事件: g_hevInt[0] = CreateEvent(NULL,FALSE,FALSE,NULL); g_hevInt[1] = CreateEvent(NULL,FALSE,FALSE,NULL); g_hevInt[2] = CreateEvent(NULL,FALSE,FALSE,NULL); ...… 查看全部问答> |
|
Windows CE 6.0 Device Emulator 问题 因为用CE6.0不多,有几个问题不明白。 1.在两台电脑同时安装CE6.0的时候,已经正确安装完毕,却发现两台电脑都出现一个问题,就是从VS2005中new 那个PB的 project的时候,Wizard界面都没有按钮显示。导致我只能瞎敲回车,才能Next> Next>。不知道 ...… 查看全部问答> |
|
请问一下,我用AVR的ATmega8的SPI口接收从机上一个不是FFFF的16位数据,从机为下降沿送数,再用串口发到电脑上显示数据,可是电脑上的串口调试助手窗口内一直显示数据为FFFF。以下是我单片机的SPI初始设置和取数程序,不知哪里设置有问题,请高手不 ...… 查看全部问答> |




