TMS320C6748_UART(1) - 基本知识
[复制链接]
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器。该总线可双向通信,可以实现去全双工传输和接收。将资料由串行通信与并行通信间作传输转换,作为并行输入成为串行输出的芯片,通常集成于其他通讯接口的连结上。其原理就是,串并转换和并串转换。
1.UART的工作原理
首先介绍几个定义:
波特率:在通信中定义的是单位时间码元的传输速率,而在UART协议下,一个码元就是一个bit。
UART数据传输格式及定义见下图所示:
发送数据过程:空闲状态,线路处于高电位;当收到发送数据指令后,拉低线路一个数据位的时间T,接着数据按低位到高位依次发送,数据发送完毕后,接着发送奇偶校验位和停止位(停止位为高电位),一帧资料发送结束。
接收数据过程:空闲状态,线路处于高电位;当检测到线路的下降沿(线路电位由高电位变为低电位)时说明线路有数据传输,按照约定的波特率从低位到高位接收数据,数据接收完毕后,接着接收并比较奇偶校验位是否正确,如果正确则通知后续设备准备接收数据或存入缓存。
由于UART是异步传输,没有传输同步时钟。为了能保证数据传输的正确性,UART采用16倍数据波特率的时钟进行采样。每个数据有16个时钟采样,取中间的采样值,以保证采样不会滑码或误码。一般UART一帧的数据位数为8,这样即使每个数据有一个时钟的误差,接收端也能正确地采样到数据。
由于UART是异步传输,没有传输同步时钟,为了能够保证数据传输的正确性,采用16倍数据波特率的时钟进行采样,也即一个bit采用16个系统时钟采样,在系统中采用一个计数器完成这个功能。例如系统时钟为150MHz,波特率为9600,采样一次也即计数器的计数周期,150000000/9600/16=976.5625,取977。那么实际波特率为150000000/977/16=9595.701,存在误差。也即如下这张图
总的来说,数据的误差与波特率设置有关,按照以下的计算方式,可以计算得到该波特率的因子,该因子相当于分频器,只能为整数,若计算得到的因子为小数,则需要四舍五入,而此时的UART的输入时钟频率经过因子分频后得到的实际波特率与设置值会存在误差,这就是误差的来源。
2.关于UART的FIFO
FIFO的必要性。在进行UART通信时,中断方式比轮询方式要简便且效率高。但是,如果没有收发FIFO,则每传输一个数据(5~8位)都要中断处理一次,效率仍然不高。如果有了收发FIFO,则可以在连续收发若干个数据(可多至14个)后才产生一次中断,然后一起处理。这就大大提高了收发效率。
接收超时问题。如果没有接收超时功能,则在对方已经发送完毕而接收FIFO未填满时并不会触发中断(FIFO满才会触发中断),结果造成最后接收的有效数据得不到处理的问题。有了接收超时功能后,如果接收FIFO未填满而对方发送已经停,则在不超过3个数据的接收时间内就会触发超时中断,因此数据会照常得到处理。
发送时,只要发送FIFO不满,数据只管往里连续放,放完后就直接退出发送子程序。随后,FIFO真正发送完成后会自动产生中断,通知主程序说:我已经完成真正的发送。
接收时,如果对方是连续不间断发送,则填满FIFO后会以中断的方式通知主程序说:现在有一批数据来了,请处理。
如果对方是间断性发送,也不要紧,当间隔时间过长时(2~3个字符传输时间),也会产生中断,这次是超时中断,通知主程序说:对方可能已经发送完毕,但FIFO未满,也请处理。
3.UART与COM口的区别
嵌入式中说的串口,一般是指UART口, 但是我们经常搞不清楚它和COM口的区别, 以及RS232, TTL等关系, 实际上UART,COM指的物理接口形式(硬件), 而TTL、RS-232是指的电平标准(电信号).
UART有4个pin(VCC, GND, RX, TX), 用的TTL电平, 低电平为0(0V),高电平为1(3.3V或以上)。
COM口是我们台式机上面常用的口(下图),9个pin, 用的RS232电平, 它是负逻辑电平,它定义+5~+12V为低电平,而-12~-5V为高电平
引脚介绍(COM口比较多pin,但是常用的也是这几个):
VCC:供电pin,一般是3.3v,在我们的板子上没有过电保护,这个pin一般不接更安全
GND:接地pin,有的时候rx接受数据有问题,就要接上这个pin,一般也可不接
RX:接收数据pin
TX:发送数据pin,
接设备的时候,一般只接GND RX TX。不会接Vcc或者+3.3v的电源线,避免与目标设备上的供电冲突。
4.UART工作模式
TMS320C6748有三个硬件串口,Uart0、Uart1、Uart2.每个串口有轮询模式(POLL)、中断模式(INT)、直接数据访问模式(DMA)。 先来分析下串口三种不同工作模式的实现机制及优缺点:
(1)轮询模式
轮询方式是对I/O设备的程序轮流查询,是早期的计算机系统对I/O设备的一种管理方式。它定时对各种设备轮流询问一遍有无处理要求。轮流询问之后,有要求的,则加以处理。在处理I/O设备的要求之后,处理机返回继续工作。
尽管轮询需要时间,但轮询要比I/O设备的速度要快得多一遍不会发生不能及时处理的问题。
当然,再快的处理机,能处理的输入输出设备的数量也是有一定限度的。而且,程序轮询占据了一部分CPU处理时间,是一种效率较低的方式,在DSP程序中很少应用。
(2)中断方式
处理器的高速和输入输出设备的低速是一种矛盾,是设备管理要解决的一个重要问题。为了提高整体效率,减少在程序直接控制方式中CPU之间的数据传送,是很必要的。
中断方式的优缺点:
I/O设备中断方式使处理器的利用率提高,且能支持多通道程序和I/O设备的并行操作。不过,中断方式仍然存在一些问题。首先,MCU要配置各种各样的输入输出设备。如果这些IO设备都通过中断处理方式并行操作,那么中断次数的急剧会造成CPU无法响应中断和出现数据丢失现象。
其次,如果IO控制器的数据缓冲区比较小,在缓冲区装满数据之后将会发生中断。那么,在数据传送过程中,发生中断的机会增多,这将耗去大量CPU处理时间。
(3)直接内存存储(DMA)方式
直接内存存储技术是指,数据在内存与IO设备间直接进行成块传输。
DMA有两个技术特征,首先是直接传送,其次是块传送。
所谓直接传送,即在内存与IO设备间传送一个数据块的过程中,不需要CPU的任何干涉,只需要CPU在过程开始时向设备发出“传送数据”的命令,然后通过中断来得知过程是否结束和下次操作是否准备就绪。
DMA与中断的区别
(1) 中断方式是数据缓冲区寄存器满之后发出中断,要求CPU进行中断处理,而DMA方式则是在所要求传送的数据块全部传送结束时要求CPU进行中断处理。这就大大减少了CPU进行中断处理的次数。
(2) 中断方式的数据传送是在中断处理时由CPU控制完成的,而DMA方式则是在DMA控制器的控制下,不经过CPU控制。这就排除了因并行设备过多而来不及处理以及因速度不匹配而造成数据丢失等现象。
DMA方式的优缺点
DMA方式中,由于IO设备直接同内存发生块的数据交换,因此效率比较高。
DMA控制器功能的强弱,是决定DMA效率的关键因素。DMA控制器需要为每次数据传送做大量的工作,数据传送单位的增大意味着传送次数的减少。另外,DMA方式窃取了时钟周期,CPU处理效率低了,要想尽量少地窃取时钟周期,就要设法提高DMA控制器的性能,这样可以较少地影响CPU处理效率。
下面讲解TMS320C6748三种工作方式程序:
`1 POLL工作方式
复制代码
1 int main(void)
2 {
3
4 PSCInit(); // 外设使能配置
5 GPIOBankPinMuxSet(); // GPIO 管脚复用配置
6
7 UARTInit(); // UART 初始化
8
9 unsigned char i; // 发送字符串
10 for(i = 0; i < 34; i++)
11 UARTCharPut(SOC_UART_1_REGS, Send);
12
13 unsigned char Receive; // 接收缓存
14 // 主循环
15 for(;;)
16 {
17 Receive=UARTCharGet(SOC_UART_1_REGS);
18 UARTCharPut(SOC_UART_1_REGS, Receive+1);
19 }
20 }
复制代码
从DSP串口 Poll模式程序可以看到,Poll模式使用比较简单,容易上手。
2 中断方式
复制代码
1 int main(void)
2 {
3 // 外设使能配置
4 PSCInit();
5
6 // GPIO 管脚复用配置
7 GPIOBankPinMuxSet();
8
9
10 // DSP 中断初始化
11 InterruptInit();
12
13 // UART 初始化
14 UARTInit();
15
16 // UART 中断初始化
17 UARTInterruptInit();
18
19 // 主循环
20 for(;;)
21 {
22 }
23 }
24
25 void UARTIsr()
26 {
27 static unsigned int length = sizeof(txArray);
28 static unsigned int count = 0;
29 unsigned char rxData = 0;
30 unsigned int int_id = 0;
31
32 // 确定中断源
33 int_id = UARTIntStatus(SOC_UART_0_REGS);
34
35 // 清除 UART2 系统中断
36 IntEventClear(SYS_INT_UART0_INT);
37
38 // 发送中断
39 if(UART_INTID_TX_EMPTY == int_id)
40 {
41 if(0 < length)
42 {
43 // 写一个字节到 THR
44 UARTCharPutNonBlocking(SOC_UART_0_REGS, txArray[count]);
45 length--;
46 count++;
47 }
48 if(0 == length)
49 {
50 // 禁用发送中断
51 UARTIntDisable(SOC_UART_0_REGS, UART_INT_TX_EMPTY);
52 }
53 }
54
55 // 接收中断
56 if(UART_INTID_RX_DATA == int_id)
57 {
58 rxData = UARTCharGetNonBlocking(SOC_UART_0_REGS);
59 UARTCharPutNonBlocking(SOC_UART_0_REGS, rxData);
60 }
61
62 // 接收错误
63 if(UART_INTID_RX_LINE_STAT == int_id)
64 {
65 while(UARTRxErrorGet(SOC_UART_0_REGS))
66 {
67 // 从 RBR 读一个字节 UARTCharGetNonBlocking(SOC_UART_0_REGS);
68 }
69 }
70 return;
71 }
复制代码
3 DMA模式
DMA模式
|