您的位置:首页 > 编程语言

TQ210_裸机编程(三)——串口通信

2014-07-14 09:36 489 查看
TQ210_裸机编程(三)——串口通信
由于我们所使用的TQ210板的L0部分已经写死 ,而且L0部分有时钟的初始化, 所以我们现在做串口通信 ,就不用再初始化时钟了。我们将会直接把程

序放在SRAM里运行。

S5PV210 包含 4 个异步收发器(UART),提供 4 个独立的异步串行输入/输出(I/O)端口。所有端口可工作于中断模式或 DMA 模式。提供高达 3Mbps

的位速率。每个 UART 包含 2 个 FIFO 用于接收和发送数据。具有可编程的波特率、红外收发、1 位或 2 位停止位、5~8 位数据位、校验。



数据发送:要发送的数据帧是可编程的。它包含 1 位起始位,5~8 位数据位,1 个可选校验位,1或2位停止位,这些都通过ULCONn寄存器来设置。在FIFO模式下发送器将发送的数据发送给Tx FIFO,在非 FIFO 模式下,发送器将要发送的

数据发送给 Tx 保持寄存器。

数据接收:和数据发送类似。

关于串口的配置有以下几个步骤:

1、配置时钟,选择时钟源

2、配置 ULCONn 寄存器:设置数据位、停止位、校验位、模式

3、配置 UCONn 寄存器:设置数据接收和发送模式、时钟源

3、设置 UFCONn:启用或静止 FIFO

4、配置 UBRDIVn 和 UDIVSLOTn:计算波特率

5、发送数据:等待发送器为空,将要发送的 8 位数据赋给发送缓存寄存器 UTXHn

6、接收数据:等待接收缓冲区有数据可读,从接收缓存寄存器 URXHn 中取出数据

首先要找到4 个异步收发器(UART),可以在配套电路图中找到。



在电路图中可以看到异步收发器的管脚地址,这里我们选用第一个收发器,GPA0_0,GPA0_1,

然后找到GPA0_0,GPA0_1,设置其参数。



从资料我们可以设置0~8位为0x22,一个是接收,一个是发送。

第一步:

我们配置ULCONn 寄存器:设置数据位、停止位、校验位、模式。同样先找到ULCONn 寄存器的资料。



/* 8-bits/One stop bit/No parity/Normal mode operation */

根据要求是设置8位长度,一个停止位,模式为No parity,校验模式为Normal,剩下的位保留。

即:ULCON0 = 0x3 | (0 << 2) | (0 << 3) | (0 << 6);

第二步:

然后接着再 配置 UCONn 寄存器:设置数据接收和发送模式、时钟源,

找到UCONn 寄存器。





主要设置第10位的时钟选择,第5位模式为Normal,因为默认值为0,所以第5位可以不设定。

传送模式为中断处理或者回滚,即2:3位设置01,

接收模式也为中断或回滚。0:1位也设置为01。

UCON0 = 1 | (1 << 2) | (0 << 10);

第三步:设置 UFCONn:静止 FIFO



第四步:

配置 UBRDIVn 和 UDIVSLOTn:计算波特率

DIV_VAL = (SCLK_UART / (bps x 16)) −1

比如配置波特率为 115200bps(串口通信一般都是这个波特率),时钟源选择 PCLK=66MHz

DIV_VAL = (66000000/(115200 x 16))-1 = 35.8 - 1 = 34.8

UBRDIV0 = 34 (DIV_VAL 的整数部分)

(num of 1's in UDIVSLOTn)/16 = 0.8 (DIV_VAL 的小数部分)(此公式在资料中已经规定)

(num of 1's in UDIVSLOTn) = 12

UDIVSLOT0 = 0xDDDD (查表)



到这里,串口的所有参数配置都已经OK了,接下来就是用串口来实现数据的接收与发送了,

下面是一个通过串口,实现 输入1使灯LED1亮,输入2,使LED2亮的程序,供大家参考。

/*uart.c*/

#define GPA0CON *((volatile unsigned int *)0xE0200000)

#define ULCON0 *((volatile unsigned int *)0xE2900000)

#define UCON0 *((volatile unsigned int *)0xE2900004)

#define UFCON0 *((volatile unsigned int *)0xE2900008)

#define UTRSTAT0 *((volatile unsigned int *)0xE2900010)

#define UTXH0 *((volatile unsigned int *)0xE2900020)

#define URXH0 *((volatile unsigned int *)0xE2900024)

#define UBRDIV0 *((volatile unsigned int *)0xE2900028)

#define UDIVSLOT0 *((volatile unsigned int *)0xE290002C)

/* UART0初始化 */

void uart_init()

{

/*

** 配置GPA0_0为UART_0_RXD

** 配置GPA0_1为UART_0_TXD

*/

GPA0CON &= ~0xFF;

GPA0CON |= 0x22;

/* 8-bits/One stop bit/No parity/Normal mode operation */

ULCON0 = 0x3 | (0 << 2) | (0 << 3) | (0 << 6);

/* Interrupt request or polling mode/Normal transmit/Normal operation/PCLK/*/

UCON0 = 1 | (1 << 2) | (0 << 10);

/* 静止FIFO */

UFCON0 = 0;

/*

** 波特率计算:115200bps

** PCLK = 66MHz

** DIV_VAL = (66000000/(115200 x 16))-1 = 35.8 - 1 = 34.8

** UBRDIV0 = 34(DIV_VAL的整数部分)

** (num of 1's in UDIVSLOTn)/16 = 0.8

** (num of 1's in UDIVSLOTn) = 12

** UDIVSLOT0 = 0xDDDD (查表)

*/

UBRDIV0 = 34;

UDIVSLOT0 = 0xDDDD;

}

static void uart_send_byte(unsigned char byte)

{

while (!(UTRSTAT0 & (1 << 2))); /* 等待发送缓冲区为空 */

UTXH0 = byte; /* 发送一字节数据 */

}

static unsigned char uart_recv_byte()

{

while (!(UTRSTAT0 & 1)); /* 等待接收缓冲区有数据可读 */

return URXH0; /* 接收一字节数据 */

}

void putchar(int c)

{

uart_send_byte(c);

/* 如果只写'\n',只是换行,而不会跳到下一行开头 */

if (c == '\n')

uart_send_byte('\r');

}

int getchar()

{

int c;

c = uart_recv_byte();

return c;

}

void puts(char *str)

{

char *p = str;

while (*p)

putchar(*p++);

putchar('\n');

}

/*main.c*/

#define GPC0CON *((volatile unsigned int *)0xE0200060)

#define GPC0DAT *((volatile unsigned int *)0xE0200064)

int main()

{

int c;

GPC0CON &= ~(0xFF << 12);

GPC0CON |= 0x11 << 12; // 配置GPC0_3和GPC0_4为输出

GPC0DAT &= ~(0x3 << 3); // 熄灭LED1和LED2

puts("UART Test in S5PV210");

puts("1.LED1 Toggle");

puts("2.LED2 Toggle");

puts("Please select 1 or 2 to Toggle the LED");

while (1)

{

c = getchar(); // 从串口终端获取一个字符

putchar(c); // 回显

putchar('\r');

if (c == '1')

GPC0DAT ^= 1 << 3; // 改变LED1的状态

else if (c == '2')

GPC0DAT ^= 1 << 4; // 改变LED2的状态

}

return 0;

}

/*start.S*/

.global _start /* 声明一个全局的标号 */

_start:

bl uart_init

/* 串口初始化 */

bl main /* 跳转到C函

数去执行 */

halt:

b halt

/*makefile*/

uart.bin: start.o uart.o main.o

arm-linux-ld -Ttext 0xD0020010 -o uart.elf $^

arm-linux-objcopy -O binary uart.elf $@

arm-linux-objdump -D uart.elf > uart.dis

%.o : %.c

arm-linux-gcc -c $< -o $@ -fno-builtin

%.o : %.S

arm-linux-gcc -c $< -o $@

clean:

rm *.o *.elf *.bin *.dis

其中makefile是将程序放到L1部分直接运行的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: