S3C2440A UART
本文是基于韦东山视频的学习笔记
UART
由于对UART还是比较熟悉的,记得以前还试过用引脚模拟,就不写原理了。
这次实现putchar,getchar 函数,波特率115200
以最简单的方式实现UART通信,而通信最重要的两点,配置好即可。
- 波特率
- 传输数据
- 其他(检验位啥的)
波特率
UART ULCON0 普通配置
同理(没想到有一天我也写这个词),查文档可得
- ULCON0 地址为 0x50000000
- [6] Infrared Mode 为正常模式:ULCON0[6] = 0
- [5:3] Parity Mode 没有校验位(简单嘛):ULCON0[5:3] = 0xx
- [2] Number of Stop Bit 每帧一个停止位 : ULCON0[2] = 0
- [1:0] Word Length 数据位数为8位: ULCON0[1:0] = 0b11
也就是 ULCON0 = 0b11 = 0x3
普通配置好像就这么设置完了
UART UCON0普通配置
UCON0 地址是0x50000004
- [15:12] FCLK Divider 不需要用,所以就不设置吧,默认0,不用
- [11:10] Clock Selection 选择PCLK : UCON0[11:10] = 00 or 10
- [9] Tx Interrupt Type 默认0,不用
- [8] Rx Interrupt Type 默认0,不用
- [7] Rx Time Out Enable 默认0,不用
- [6] Rx Error Status Interrupt Enable 默认0,不用
- [5] Loopback Mode 默认0,不用
- [4] Send Break Signal 默认0,不用
- [3:2] Transmit Mode 设置为中断模式,没其他可以选了:UCON0[3:2] = 0b01
- [1:0] Receive Mode 设置为中断模式,没其他可以选了:UCON0[1:0] = 0b01
即 UCON0 = 0x5 or 0x805
UART状态寄存器
FIFO 和 AFC 都先不用,直接看状态寄存器吧
UTRSTAT0 地址为 0x50000010
- [2] Transmitter empty 数据发完了就是1
- [1] Transmit buffer empty 数据缓存空的就是1
- [0] Receive buffer data ready 有数据可接收时是1
UTXH0 地址为 0x50000020(L)1
- [7:0] TXDATAn 数据都在这!
URXH0 地址为 0x50000024(L)1
- [7:0] RXDATAn 数据都在这!
波特率寄存器
Each UART’s baud-rate generator provides the serial clock for the transmitter and the receiver. The source clock for the baud-rate generator can be selected with the S3C2440A’s internal system clock or UEXTCLK. In other words, dividend is selectable by setting Clock Selection of UCONn. The baud-rate clock is generated by dividing the source clock (PCLK, FCLK/n or UEXTCLK) by 16 and a 16-bit divisor specified in the UART baud-rate divisor register (UBRDIVn). The UBRDIVn can be determined by the following expression:
UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
得到了一条重要的公式。想要得到相应波特率,算出相应的UBRDIVn再配置即可。UART clock 可以是 PCLK, FCLK/n or UEXTCLK, 通过 UCONn 配置。
查阅手册可得,就不贴图了,感觉贴图了好难看。
UCON0 地址是0x50000004
UART clock 设置为PCLK :UCON0[11:10] = 0b00 or 0b10
上次我们已经设置了 PLCK 50MHz,带入公式
UBRDIVn = (int)( 50 000 000 / ( 115200 x 16) ) –1 = 26.12 ≈ 26
直接看文档得,UBRDIV0 地址为 0x50000028
- [15:0] UBRDIV0 设置为26:UBRDIV0[15:0] = 26
即 UBRDIV = 26 = 0x1A
配置引脚
同样不贴图了
TXD0 - GPH2
RXD0 - GPH3
GPHCON 地址为 0x56000070
- [7:6] GPH3 设置为RXD[0]:GPHCON[7:6] = 0b10
- [5:4] GPH2 设置为TXD[0]:GPHCON[5:4] = 0b10
至此,相关配置完毕
uart.c
#define GPHCON (*((volatile unsigned int *)0x56000070))
#define ULCON0 (*((volatile unsigned int *)0x50000000))
#define UCON0 (*((volatile unsigned int *)0x50000004))
#define UTRSTAT0 (*((volatile unsigned int *)0x50000010))
#define UBRDIV0 (*((volatile unsigned int *)0x50000028))
#define UTXH0 (*((volatile unsigned char *)0x50000020))
#define URXH0 (*((volatile unsigned char *)0x50000024))
#define GPHUP (*((volatile unsigned char *)0x56000078))
void uart0_config()
{
/* 配置引脚为TXD和RXD
- [7:6] GPH3 设置为RXD[0]:GPHCON[7:6] = 0b10
- [5:4] GPH2 设置为TXD[0]:GPHCON[5:4] = 0b10
*/
GPHCON &= ~((3<<4)|(3<<6)); //清零
GPHCON |= ((1<<5)|(1<<7)); //置一
GPHUP &= ~((1<<2) | (1<<3)); /* 使能内部上拉 */
/* 配置ULCON0
- [6] Infrared Mode 为正常模式:ULCON0[6] = 0
- [5:3] Parity Mode 没有校验位(简单嘛):ULCON0[5:3] = 0xx
- [2] Number of Stop Bit 每帧一个停止位 : ULCON0[2] = 0
- [1:0] Word Length 数据位数为8位: ULCON0[1:0] = 0b11
- 也就是 ULCON0 = 0b11 = 0x3
*/
ULCON0 = 3;
/* 配置UCON0
- [15:12] FCLK Divider 不需要用,所以就不设置吧,默认0,不用
- [11:10] Clock Selection 选择PCLK : UCON0[11:10] = 00 or 10
- [9] Tx Interrupt Type 默认0,不用
- [8] Rx Interrupt Type 默认0,不用
- [7] Rx Time Out Enable 默认0,不用
- [6] Rx Error Status Interrupt Enable 默认0,不用
- [5] Loopback Mode 默认0,不用
- [4] Send Break Signal 默认0,不用
- [3:2] Transmit Mode 设置为中断模式,没其他可以选了:UCON0[3:2] = 0b01
- [1:0] Receive Mode 设置为中断模式,没其他可以选了:UCON0[1:0] = 0b01
**即 UCON0 = 0x5 or 0x805**
*/
UCON0 = 0x5;
/* 配置波特率UBRDIVn
* UBRDIVn = (int)( 50 000 000 / ( 115200 x 16) ) –1 = 26.12 ≈ 26
*/
UBRDIV0 = 26;
}
int putchar(int c)
{
/* UTRSTAT0寄存器
- [2] Transmitter empty 数据发完了就是1
- [1] Transmit buffer empty 数据缓存空的就是1
- [0] Receive buffer data ready 有数据可接收时是1
*/
while(!(UTRSTAT0&(1<<2))); //当寄存器第二位是1时一直循环
UTXH0 = (unsigned char)c; //UTXH0是1个字节的
}
int getchar()
{
/* UTRSTAT0寄存器
- [2] Transmitter empty 数据发完了就是1
- [1] Transmit buffer empty 数据缓存空的就是1
- [0] Receive buffer data ready 有数据可接收时是1
*/
while(!(UTRSTAT0&(1<<0)));
return URXH0;
}
int puts(const char *s)
{
while(*s)
{
putchar(*s++);
}
}
main.c
void uart0_config();
int putchar(int c);
int getchar();
int puts(const char *s);
int main()
{
unsigned char c;
uart0_config(); //配置UART
puts("Hello!!!\n\r");
while (1)
{
c = getchar();
if(c == '\r') putchar('\n');
if(c == '\n') putchar('\r');
putchar(c);
}
return 0;
}