TQ210——S5PV210串口通信

TQ210——S5PV210串口通信

 

1、  串行与并行通信

      串行通道中,有效信息被编码后串行的从单根传输线上传送出去。譬如发送ASCII字符’a’,我们可以将’a’对应的ASCII码97(0x61)分作8个bit在传输线上顺序依次传输。

      与串行传输相对应的是并行传输,并行传输一般有多根并列的传输线可以同时传输多个bit数据。譬如8线的并行传输,可以同时传输8个比特。因此在线速相同的情况下并行传输效率更高,但同时布线成本更高。

      串行硬件接口简单,只需要 3 根线:一是底线,二是发送,三是接收。

      UART 使用标准的 TTL/CMOS 逻辑电平(0~5V)来表示数据,用 1 表示高 电平,用 0 表示低电平,为了增强数据的抗干扰能力、提高传输距离,通常将 TTL/CMOS 逻辑电平转换成 RS232 逻辑电平,一般用 1 表示(-3~12V),用 0 表 示 (3~12V)

(1)、帧:因为串行通信只有一根传输线,单位时间内只能传输一个比特位,因此要对传输信息进行编码发送。以常用的ASCII编码为例,则传输一个字符的ASCII编码称为一帧。一帧信息包括起始位、数据位、校验位、停止位等部分。

(2)起始位:一帧的开始标志。

(3)数据位:帧内有效数据,长度可配置为6、7、或8bit,一般ASCII编码下均使用8bit数据位。

(4)校验位:可选择奇/偶/无校验

(5)停止位:一帧的停止标志。停止位后传输线变为空闲状态,一直到下一帧的起始位

(6)波特率:串行传输中传输线上每秒钟传输的bit数称为波特率(Baudrate),波特率越大传输速率越快,同时传输对误差和干扰越敏感越容易出错。

 

2、  S5PV210 —— UART4个独立的异步串行IO

      S5PV210的UART支持查询模式(Polling)、中断模式(Interrupt)、DMA模式三种模式

      Polling模式可以用来实现stdio

      中断模式中,CPU可以在不影响主任务的情况下,使用中断响应处理串行通信,因此可以用来实现高效的串行发送和接收。如果开启FIFO模式,效率将更高。

      DMA模式中使用DMA通道来传输信息,适合批量数据的串行传输需要。

      S5PV210的UART模块有两个可选时钟源:PCLKor SCLK_UART。我们大多数选择 PCLK 作为波特 率发生器的时钟源输入。

 

3、  寄存器

(1) ULCON

      ULCON中主要设置串行通信的数据格式,一般会设置为0x03(普通模式、无校验、1停止位、8数据位)。

      UCON中主要设置Tx/Rx中断类型(必须设置为Level,而不能是Pulse,这是S5PV210本身决定的)以及Rx/TxMode(如果不使用DMA,则一般会选择Interruptrequest or polling mode),所以UCON的常规赋值为0x305。

 

(2)UFCON

      UFCON中设置Rx/TxFIFO enable/disable,用来使能或禁止FIFO模式

      如果使能FIFO模式,则同时需要设置各串口的发送与接收FIFO的触发等级

      注意接收时,RxFIFO中的实际值大于RxFIFO的触发等级时会触发RxInterrupt;而发送时,TxFIFO中的实际值小于TxFIFO时即会触发Tx Interrupt。因此一般会先填充TxFIFO然后再使用Tx Interrupt

 

(3)STATUS寄存器

      UTRSTATn寄存器中记录发送(FIFO)空与接收ready状态标志位。我们在发送前必须检查发送空标志位,待其为1时才可发送;接收前必须检查接收好状态位,待其为1时才可去读接收字符。

      UERSTATn寄存器记录通信过程中的错误,如帧错误、奇偶校验错误、覆盖错误等。

      UFSTATn记录FIFO模式下的相关状态标志。

 

(4)发送/接受缓冲器

UART0~3各有一个发送缓冲寄存器和一个接收缓冲寄存器

UART发送时,将要发送的数据(一般为1Byte)放入UTXHn即可

UART接收时,从URXHn读取接收到的数据

 

(5)波特率设置寄存器

      S5PV210的UART波特率设置寄存器与S3C2440等有很大不同,除UBRDIVn外增加了UDIVSLOTn寄存器作为精细调节以减小误差。

对于UBRDIVn:

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

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

对于UDIVSLOTn:

       DIV_VAL = UBRDIVn + (num of 1's inUDIVSLOTn)/16

 比如配置波特率为 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 (查表)

 

(6)UARTINTERRUPT1

      当一个UARTinterrupt来临时,会在UINTSP寄存器中产生一个相应bit的挂起标志。同时若UINTM中相应bit设置为中断允许,则会在UINTP中产生一个中断挂起。


(7)UARTINTERRUPT2

      UART使用的中断共有4个,其中常用的是接收中断RXD。串口模块使能RXDInterrupt时,当串口接收到信息时则会触发中断,CPU响应中断并从URXHn读出数据。中断机制的引入,使CPU具有了一边执行主程序、一边进行串口通信接收的宏观上的并行能力。

 

4、串口编程操作步骤如下:
(1)、配置时钟,选择时钟源
(2)、配置 ULCONn 寄存器:设置数据位、停止位、 校验位、模式
(3)、配置 UCONn 寄存器:设置数据接收和发送模式、时钟源
(4)、设置 UFCONn:启用或静止 FIFO
(5)、配置 UBRDIVn 和 UDIVSLOTn:计算波特率
(6)、发送数据:等待发送器为空,将要发送的 8 位数据赋给发送缓存寄存器 UTXHn
(7)、接收数据:等待接收缓冲区有数据可读,从接收缓存寄存器 URXHn 中取出数据

 

.global _start                                  
_start:
              bl uart_init                  /* 串口初始化*/
              bl main                       /* 跳转到C函数去执行*/
halt:
              b halt

#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             *((volatileunsigned 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/Normalmode operation */
       ULCON0 = 0x3 | (0 << 2) | (0<< 3) | (0 << 6);
 
       /* Interrupt request or polling mode/Normaltransmit/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');
}

#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 Togglethe 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值