精华内容
下载资源
问答
  • 串口通信数据格式与解析

    千次阅读 2017-08-31 10:43:13
    串口通信的传输格式: 串行通信中,线路空闲时,线路的 TTL 电平总是高,经反向 RS232 的电平总是低。一个数据 的开始 RS232 线路为高电平,结束时 Rs232 为低电平。数据总是从低位向高位一位一位的传 输。示波器...
    串口通信的传输格式:
    串行通信中,线路空闲时,线路的 TTL 电平总是高,经反向 RS232 的电平总是低。一个数据
    的开始 RS232 线路为高电平,结束时 Rs232 为低电平。数据总是从低位向高位一位一位的传
    输。示波器读数时,左边是数据的高位。
    例如,对于 16 进制数据 55aaH,当采用 8 位数据位、1 位停止位传输时,它在信号线上的波
    形如图 1(TTL 电平)和图 2(RS-232 电平)所示。
    55H=01010101B,取反后 10101010B,加入一个起始位 1,一个停止位 0,55H 的数据格式为
    1010101010B;
    aaH=10101010B,取反后 01010101B,加入一个起始位 1,一个停止位 0,55H 的数据格式为

    1101010100B;


    串口通信的接收过程:(异步通信:接收器和发送器有各自的时钟;同步通信:发送器和接收
    器由同一个时钟源控制。RS232 是异步通信)
    (1)开始通信时,信号线为空闲(逻辑 1),当检测到由 1 到 0 的跳变时,开始对“接收时钟”
    计数。
    (2)当计到 8 个时钟时,对输入信号进行检测,若仍为低电平,则确认这是“起始位”,而不
    是干扰信号。
    (3)接收端检测到起始位后,隔 16 个接收时钟,对输入信号检测一次,把对应的值作为 D0
    位数据。若为逻辑 1, 作为数据位 1;若为逻辑 0,作为数据位 0。
    (4)再隔 16 个接收时钟,对输入信号检测一次,把对应的值作为 D1 位数据。….,直到全部
    数据位都输入。
    (5)检测校验位 P(如果有的话)。
    (6)接收到规定的数据位个数和校验位后,通信接口电路希望收到停止位 S(逻辑 1),若此时
    未收到逻辑 1,说明出现了错误,在状态寄存器中置“帧错误”标志。若没有错误,对全部数据
    位进行奇偶校验,无校验错时,把数据位从移位寄存器中送数据输入寄存器。若校验错,在
    状态寄存器中置奇偶错标志。
    (7)本幀信息全部接收完,把线路上出现的高电平作为空闲位。
    (8)当信号再次变为低时,开始进入下一幀的检测。

    展开全文
  • 1.最近在开发一款Labview串口通信软件,功能是实现PCsony摄像机云台的数据通信。主要是通过PC发送16进制指令控制云台的转动,方便做一些测试。 遇到的问题:一开始没注意格式问题,只是纯粹的将16进制数据放入...

    1.最近在开发一款Labview串口通信软件,功能是实现PC与sony摄像机云台的数据通信。主要是通过PC发送16进制指令控制云台的转动,方便做一些测试。

    遇到的问题:一开始没注意格式问题,只是纯粹的将16进制数据放入VISA WRITE函数的写入缓冲区。但是忽略了一个问题,就是Labview软件中的程序无论是接收还是发送数据都是字符串的格式,所以遇到其他格式通信的时候需要做相关转换操作。

    在论坛找了很多资料,都没找到合适的解决方案。最终找到这个,“VISA Write的写入缓冲区字符串常量上右键>>十六进制显示”。(之前在一个WORD文档里面找到的也是这个方案,只是资料说的不够直白,当时没反应过来:

     

     “如果这些数据是静态的,也就说在程序设计阶段要传输的数据就已经确定了,在这种情况下,首先设置VISA Write的write buffer的显示属性为Hex Display,然后直接输入要发送的16进制字符串就可以了。串口设备的控制命令通常是由一个或多个16进制字符组成的,当我们需要对其进行控制时经常会采用这种方法发送控制命令。”

    上面这段文字中的显示属性其实就是写入缓冲区的字符串常量右键之后的“16进制显示”选项,只不过因为我用的是中文版软件,一时没反应过来。


    2.使用LabVIEW发送数据

    还有一个问题是使用LabVIEW发送数据的问题

    ①如果下位机接收的是字符串数据类型的话,直接用VISA写入对应的字符串就行了,现在的仪器一般都是接收字符串的,所以可以直接使用VISA发送而不需要转换。

    ②如果下位机接收的是数值型数据的话,就需要转换一下,其中数值型又是十进制和十六进制二种用得比较多,这二种数据间相互转换一下就行了,其实是一样的。

    由于在LabVIEW中字符串直接有十六进制的显示方式,所以发送十六进制的数据比较方便,比如要发送十六进制数值类型的“0xAF”,那么在VISA Write的写入缓冲区字符串常量上右键>>十六进制显示,直接输入“AF”即可,那么下位机接收到的就是正确的数据(十六进制数值类型)了。

    展开全文
  • LabVIEW上位机与串口通信

    千次阅读 2017-08-21 17:16:52
    定义通信格式及功能因为数据不算复杂,所以定义简单下位机帧格式:帧头(0xAA) 类型字节 数据低8位 数据高8位 保留字节1 保留字节2 校验字节 如果要传送的数据比较多/复杂,则可以参考ModuleBus协议!主要功能包括...

    定义通信格式及功能

    因为数据不算复杂,所以定义简单下位机帧格式:

    帧头(0xAA) 类型字节 数据低8位 数据高8位 保留字节1 保留字节2 校验字节
    

    如果要传送的数据比较多/复杂,则可以参考ModuleBus协议!

    主要功能包括:

    • 对帧中的类型字节进行解析,并多通道显示在示波器上
    • 帧偏差校正(这个一般人可能都没有做,造成数据丢失,而我这只要串口传输的数据没错,就能无错漏的解析每一帧)
    • 实时显示读取的每个字节/双字节/4字节
    • 信号保存,保存文件名自动按时间命名,适合查阅
    • 信号回放
    • 对信号进行解析,用指示灯显示

    界面展示

    123

    程序关键点展示

    4

    上面虽然简单,但却是功能的最主要部分,包括帧头查找和错帧处理的程序。错帧发送的情况是:比如从串口中独到的帧并不是从帧头开始而是帧中间开始,如

    0x12(数据) 0x00 0x00 0x00 0xAA(帧头) 0x00
    

    其前面一帧可能是这样:

    ... 0xAA(帧头) 0x01(类型) 0x01(数据)
    

    这样,按查找帧头的方法,数据0x12就会丢失,实际数据按理应该是0x02*256+0x01,错帧处理就是将上一帧尾部不足一帧的部分加到下一帧中,这样下一帧就变成了:

    0xAA(帧头) 0x01(类型) 0x01(数据) 0x12(数据) 0x00 0x00 0x00 0xAA(帧头) 0x00
    

    5

    判断类型过程很简单,使用switch结构就行了(LabVIEW中就是条件结构同时实现了if和switch),编程时就是注意必须设置默认分支就行!

    6

    文件保存我使用了数据表,因为它确实简单,这里的亮点是增加了按时间保存的功能,相当于将时间字符串加入到文件名中,这样便于后期对采集的数据进行查找,不至于混乱。

    7

    波形回放就是将存储在数据表中的程序重新显示一遍,比较简单!

    到现在为止,完整的程序请到https://github.com/xiahouzuoxin/zxSerial下载!

    仅供研究使用,谢谢!

    展开全文
  • 为解决串口通信中的数据传输容易出错、可靠性差且容错能力低等问题,设计并实现一种串 1:2通信高可靠性应用协议,并将此协议应用在列控产品中。首先介绍串口通信协议的数据包格式, 通过在数据包格式定义中设置...
  • 1.2 串口通信格式 1.2.1 RS232电平和TTL电平 1.2.2 波特率 1.2.3 数据帧构成 2. S5PV210 UART模块解析 2.1 概述 2.2 构成部件 2.2.1 Buad-rate Generator 2.2.2 Trsansmitter 2.2.3 Recei

    目录

    1. 串口通信基本概念

    1.1 通信基础概念

    1.1.1 电平信号 & 差分信号

    1.1.2 串行通信 & 并行通信

    1.1.3 异步串行通信 & 同步串行通信

    1.2 串口通信格式

    1.2.1 RS232电平和TTL电平

    1.2.2 波特率

    1.2.3 数据帧构成

    2. S5PV210 UART模块解析

    2.1 概述

    2.2 构成部件

    2.2.1 Buad-rate Generator

    2.2.2 Trsansmitter

    2.2.3 Receiver

    2.2.4 Control unit

    2.3 自动流控(Auto Flow Control,AFC)

    2.3.1 概述

    2.3.2 实现

    2.4 中断与DMA请求

    2.4.1 UART的7种状态

    2.4.2 中断产生列表

    2.4.3 UART DMA请求

    2.5 错误状态FIFO

    2.5.1 概述

    2.5.2. 注意事项

    2.6 红外模式

    3. S5PV210 UART程序设计

    3.1 核心寄存器解析

    3.1.1 ULCONn

    3.1.2 UCONn

    3.1.3 UFCONn & UFSTATn

    3.1.4 UTRSTATn & UERSTATn

    3.1.5 UTXHn & URXHn

    3.1.6 UBRDIVn & UDIVSLOTn

    3.1.7 UINTMn & UINTSPn & UINTPn

    3.2 串口初始化&收发数据代码解析

    3.2.1 串口初始化代码解析

    3.2.2 串口收发函数解析

    3.3 基于中断的Rx代码解析

    3.3.1 中断初始化

    3.3.2 ISR

    4. printf移植解析

    4.1 什么是stdio

    4.2 C语言对可变参函数的支持

    4.3 移植printf/scanf函数

    4.3.1 移植代码来源

    4.3.2 printf/scanf工程的组织和编译

    4.4 printf/scanf函数工作原理

    4.4.1 printf函数工作原理

    4.4.2 scanf函数工作原理

    5. 自建bootloader超过BL1长度限制的解决方案

    5.1 dnw下载

    5.2 SD卡烧写


    1. 串口通信基本概念

    1.1 通信基础概念

    1.1.1 电平信号 & 差分信号

    电平信号 & 差分信号用于说明信号线上如何表示数据0和1

    ① 电平信号

    电平信号中有一根电平参考线(一般为GND),信号线上的数据值由信号线和参考线上的电压差决定

    ② 差分信号

    差分信号中没有参考电平,都是信号线,只是2路信号振幅相同/相位相同/极性相反。信号线上的数据值由信号线之间的电压差决定。

    说明:电平信号的2根通信线之间的电平差值容易受到干扰;差分信号抗干扰能力较强(尤其是共模干扰),因此传输质量比较稳定。

    1.1.2 串行通信 & 并行通信

    ① 串行通信

    计算机与IO设备之间数据传输的各位按顺序依次传送,通常数据在一根数据线或一对差分线上传输。

    一般特点:速度慢/成本低/适合远距离传输

    ② 并行通信

    计算机与IO设备之间通过多条传输线交换数据,数据各位同时传送

    一般特点:速度快/成本高/适合近距离传输

    注意1:一些差分串行通信总线(e.g. RS485/RS422/USB)抗干扰能力强,传输距离远,速度也比较快~~

    注意2:CPU内部均是采用并行传输(数据总线)

    1.1.3 异步串行通信 & 同步串行通信

    ① 异步串行通信

    特点:

    a. 以字符为单位传送信息

    b. 相邻2个字符之间的间隔为任意长

    c. 因为一个字符的比特位长度有限,所以接收时钟和发送时钟只要相近即可(即发送方和接收方可以各自维护时钟)

    d. 字符间异步,字符内同步

    补充:如何理解字符内同步?

    每个字符的传输通过起始位 & 停止位进行界定

    数据格式:

    a. 1位起始位,规定为低电平(空闲时为高电平,将信号线拉低表示起始位)

    b. 5 ~ 8位数据位,即要传送的有效信息,一般设置为8位。从LSB开始传输,靠时钟定位。

    c. 1位奇偶校验位,可以构成奇校验(使“1”的位数为奇数)或偶校验(使“1”的位数为偶数)

    d. 1 ~ 2位停止位,规定为高电平

    ② 同步串行通信

    特点:

    a. 以数据块为单位

    b. 在一个数据块(信息帧)内,字符与字符之间无间隔

    c. 因为一次传输的数据块中数据较多,所以接收时钟和发送时钟必须严格同步,通常要有同步时钟(e.g. SPI & I2C)。

    d. 字符内部与字符之间均同步

    说明:经过多年发展,最终胜出的是异步/串行/差分通信,如USB和网络通信

    1.2 串口通信格式

    串口通信的基本特点:异步/串行/电平信号

    1.2.1 RS232电平和TTL电平

    ① RS232电平

    逻辑1:-3 ~ -15V

    逻辑0:+3 ~ +15V

    ② TTL电平

    逻辑1:+3.5 ~ +5V

    逻辑0:< 0.4V

    ③ 使用场景

    RS232电平幅值范围较大,适合干扰大/距离远的情况。原先PC机以及工业应用中,均使用RS232串口

    TTL电平赋值范围较小,适合干扰小/距离近的情况。TTL电平一般用在电路板内部2个芯片之间

    ④ 电平转换

    X210开发板(包括OK210开发板)使用管脚引出的串口均为TTL电平;同时也使用了TTL转RS232芯片,并使用DB9接口引出。

    注意:串口电路中仅使用了DB9接口中的Tx/Rx接口(同时GND接地),其余接口并未使用(也就是说,流控及其他功能均无法使用)

    说明:编程时并不考虑电平标准

    1.2.2 波特率

    ① 波特率和比特率

    波特率:信号变化的次数(即每秒采样的次数),也称为码元速率(即得到一个信号的频率)

    比特率:数据传输速率,单位为bps(bit per second)

    ② 波特率和比特率的关系

    如果信号分为两级:0、1,那么一次信号变化可表示1bit,所以比特率 = 波特率

    如果信号分为八级:0 ~ 7,那么一次信号变化可表示3bit,所以比特率 = 3 * 波特率

    因此,如果信号分为v级,则比特率 = log2v * 波特率

    上图中两个信号的波特率相同(即信号到达的速率相同,竖虚线等宽),但下面的信号每次携带2 bit(信号分为四级)信息,所以比特率是上面信号的2倍

    ③ 串口波特率

    由于在串口中信号只分为2级,所以比特率 = 波特率,也就是串口通信时每秒可以传输多少个二进制位。

    由于串口通信属于异步传输,所以收发双方各自维护波特率(也就是串口通信的时钟)

    1.2.3 数据帧构成

    串口通信按帧传输,每个周期由起始位 + 数据位 + 奇偶校验位 + 停止位构成。具体格式见上文异步串行通信部分。

    2. S5PV210 UART模块解析

    2.1 概述

    ① UART模块负责CPU和UART之间的数据传输(包含了串并转换时序控制

    ② S5PV210共有4路UART接口,且均可基于中断/DMA工作

    ③ 最高支持3Mbps速率

    ④ 每条UART通道包含2条FIFO(分别用于收/发),其中ch0 - 256B/ch1 - 64B/ch2 - 16B/ch3 - 16B

    ⑤ ch0 - ch3支持红外模式

    ⑥ ch0 - ch2支持自动流控(AFC)

    2.2 构成部件

    2.2.1 Buad-rate Generator

    波特率发生器使用PCLK或SCLK_UART分频生成所需的波特率

    在我们的示例中,使用PCLK_PSYS作为UART模块的时钟源

    2.2.2 Trsansmitter

    发送部件由发送FIFO发送移位器组成,在非FIFO模式下,相当于只用FIFO的一个字节。

    程序将要发送的数据写入Tx FIFO后,将自动拷贝到Tx shifter并逐位传输到TxD引脚。

    2.2.3 Receiver

    接收部件由接收FIFO接收移位器组成,在非FIFO模式下,相当于只用FIFO的一个字节。

    从RxD引脚接收到的数据逐位移入Rx shifter,然后自动拷贝到Rx FIFO中。

    说明:通过FIFO和shifter的配合,实现了UART的串并转换(CPU内部数据传输均为并行)

    2.2.4 Control unit

    控制整个UART收发流程

    2.3 自动流控(Auto Flow Control,AFC)

    2.3.1 概述

    ① 流控的目的是让串口通信可靠,在发送方速率比接收方处理能力强时,流控可以确保不丢帧(所谓流控,就是控制发送端的发送速率,而主导调控发送速率的是接收端)。

    当前不使用流控,是因为串口主要用于输出调试信息,作为接收方的PC,处理能力远比SoC强。

    ② S5PV210的UART0和UART1支持AFC;如果将TxD3/RxD3引脚设置为nRTS2/nCTS2功能,则UART2也支持AFC(当然,此时UART3无法使用~~)

    2.3.2 实现

    S5PV210为实现AFC,需要用到RTS/CTS引脚,其中RTS为outputCTS为input

    术语说明:

    RTS:Require To Send,发送请求,为输出信号,用于指示本设备准备好接收数据

    CTS:Clear To Send,允许发送,为输入信号,用于判断是否可以向对方发送数据

    一般使用硬件流控时,将两端设备的RTS & CTS交叉连接

    ① 发送数据

    在AFC中,nCTS信号表示对端UART的接收FIFO已准备好接收数据。所以当发送端nCTS信号生效时,可以将数据写入自身发送FIFO(传输则由Control Unit控制完成)

    ② 接收数据

    在AFC中,nRTS信号表示自身接收FIFO准备好接收数据。所以在接收端接收数据前,需要使能nRTS信号

    说明:根据上文分析,通信两端的CTS/RTS信号交叉连接,整个流控过程实际是由接收端控制(因为只有RTS信号是输出信号)。

    当接收端接收FIFO无法继续接收数据时,使得RTS信号失效,则发送端无法收到CTS信号,所以不再继续发送。

    当接收端接收FIFO出现空闲,可以继续接收时,将RTS信号使能,则发送端收到CTS信号,将继续发送数据。

    在S5PV210中,RTS和CTS均是低电平有效,所以拉低RTS使能该信号时,对端连接的CTS也将生效。(注意寄存器值与高低电平的关系~~)

    注意:如果将S5PV210的UART与Modem连接,需要禁止UMCONn寄存器的AFC位,并且通过软件控制nRTS信号

    2.4 中断与DMA请求

    2.4.1 UART的7种状态

    在S5PV210中,UART共有7种状态,分别记录在UTRSTAT和UERSTAT寄存器中,可以分为3类:

    ① Tx

    Tx buffer empty / Tx shifter empty

    ② Rx

    Rx buffer data ready

    ③ Error

    Overrun error:缓冲区溢出错误,即新数据已经覆盖旧的未读数据

    Parity error:奇偶校验错误

    Frame error:帧错误,即收到的数据没有有效的停止位

    Break condition:UART发送端可以产生break信号,将串口输出状态强制为logic 0 state,并保持一个数据帧的长度(后文可知,发出break信号有寄存器可供设置)。如果break信号超过一个数据帧的长度,接收端将检测到break condition。

    2.4.2 中断产生列表

    Type

    FIFO Mode

    Non-FIFO Mode

    Rx interrupt

    ① Rx FIFO数据量 >= Rx FIFO阈值

    ② Rx FIFO数据量 < Rx FIFO阈值,同时

    3个字长时间没有收到数据(处理尾字节

    Rx holding register中有数据

    Tx interrupt

    Tx FIFO数据量 <= Tx FIFO阈值

    Tx holding register中无数据

    Error interrupt

    frame error/parity error/break condition/

    overrun error触发。且当多个错误同时发生

    时,只触发一次中断

    同FIFO Mode

    注意事项:

    ① 产生Tx/Rx中断的配置

    UART工作在中断或轮询模式 && 中断mask寄存器对应位打开

    ② 产生Error中断的配置

    使能Rx Error中断 && 中断mask寄存器对应位打开

    ③ 中断的共享与识别

    S5PV210中,每个UART只有一个中断源,所以如果同时使能UART的多种中断,需要在ISR中进行识别。

    ④ Tx中断注意点

    根据Tx中断的触发条件,只要Tx FIFO数据量 <= Tx FIFO阈值就会触发,因此建议先向Tx FIFO中写入数据再使能Tx中断

    个人:使用中断模式发送数据时,应该,

    a. 默认先关闭中断

    b. 有数据要发送时,先向Tx FIFO中写入数据,然后使能中断

    c. 在ISR中判断是否还有数据要发送,如果有,则向Tx FIFO中继续写入;如果没有,则关闭中断

    这套流程不仅适用于基于中断的串口发送,其他基于中断的接口发送也遵循该流程(e.g. SPI)

    上述流程的核心在于中断使能和关闭的时机,如果是基于中断的数据接收,要点也在于此,但是接收流程的设计相对简单,可以设置阈值坐等数据到来。如果等待过程中发生timeout,比如发生尾字节中断,可以在ISR中设置再次进入等待

    ⑤ 由于S5PV210的中断控制器为电平触发,因此UART的中断信号类型只能设置为电平模式

    2.4.3 UART DMA请求

    ① 如果设置UART工作在DMA模式,那么在上文中产生Tx/Rx中断的条件下就不会产生中断,而是产生DMA请求

    ② DMA模式一般配合FIFO使用(否则意义不大~~)

    ③ DMA burst size可设置为1B或4B,建议FIFO阈值与DMA burse size匹配

    ④ DMA传输会一直持续到满足FIFO阈值

    2.5 错误状态FIFO

    2.5.1 概述

    ① 错误状态FIFO用于标识Rx FIFO中哪个数据是错误的及其错误类型

    ② 每个错误状态FIFO记录一种错误,并与Rx FIFO的位置对应

    2.5.2. 注意事项

    ① 如果使能了Error中断,只有当错误数据被读取时(通过读取URXHn寄存器)才会触发中断

    ② 为清除错误FIFO中的状态,需要同时读取URXHn和UERSTATn寄存器

    2.6 红外模式

    ① UART的红外模式需要在串口之外结合红外编解码器实现

    ② 红外模式的通信的原理是发送方在固定时间间隔向接收方发送红外信号(表示1)或者不发送红外信号(表示0)

    当串口启用IrDA模式,我们向串口写数据时,这些数据就以红外光的方式向外发射出去。

    3. S5PV210 UART程序设计

    3.1 核心寄存器解析

    3.1.1 ULCONn

    ULCONn(UART Line Control)寄存器主要用于设置数据帧格式,一般设置为:

    8位数据位 + 无奇偶校验 + 1位停止位

    3.1.2 UCONn

    UCONn(UART Control)寄存器主要用于设置UART的工作模式,需要注意以下字段:

    ① Tx/Rx/Error中断使能设置(注意,Tx/Rx的中断类型只能是电平)

    ② 此处选择PCLK_PSYS作为UART的时钟源

    ③ 注意Rx time-out中断,该中断就是用于处理尾字节,类型为Rx中断

    个人:从该寄存器可知,要实现可靠的通信协议,一定是需要硬件层面保障的(e.g. 各种错误状态的标识与通知机制)

    而软件层面的设计,需要充分利用这些硬件机制

    3.1.3 UFCONn & UFSTATn

    UFCONn(UART FIFO Control)寄存器主要用于使能FIFO及设置Tx/Rx FIFO触发中断的阈值。

    注意不同channel的UART FIFO深度不同~~

    UFSTATn(UART FIFO Status)寄存器表征了当前FIFO的状态,主要关注Tx/Rx FIFO中的数据量,在使能FIFO和中断的情况下,需要在ISR中根据该寄存器读写相应数量的数据。

    3.1.4 UTRSTATn & UERSTATn

    上文中说明的UART的7种状态就保存在这2个寄存器中

    UTRSTATn(UART Tx/Rx Status)寄存器标识Tx/Rx相关状态,需要注意以下字段:

    ① Transmitter empty是指Tx buffer和Tx shifter均为空

    ② Transmit buffer empty仅指Tx buffer为空,在Non-FIFO模式中,此时就触发中断或DMA请求

    当使能FIFO时,应该检查UFSTAT寄存器而不是该寄存器

    UERSTATn(UART Error Status)寄存器标识Rx过程中发生的各种错误。

    注意:读取UERSTATn寄存器就可将相关标志位自动清零

    3.1.5 UTXHn & URXHn

    UTXHn(UART Transmit Buffer[Holding Register & FIFO register])和URXHn(UART Receive Buffer Register[Holding Register & FIFO register])是读写串口数据时实际操作的寄存器。

    在Non-FIFO模式下,就是Holding Register;在FIFO模式下,则是FIFO register

    3.1.6 UBRDIVn & UDIVSLOTn

    UBRDIVn(UART Channel Baud Rate Division)和UDIVSLOTn(UART Channel Dividing Slot)寄存器共同实现波特率的设置。其中UBRDIVn负责主分频,UDIVSLOTn用于辅助校准,以提高波特率的精度。

    计算公式如下:

    UBRDIVn = (PCLK / (bps * 16)) - 1的整数部分

    UDIVSLOTn = (PCLK / (bps * 16)) - 1的小数部分 * 16 的整数部分构造而来

    在本示例中,PCLK = 66.7MHz,波特率设置为115200,因此

    UBRDIVn = (66700000 / (115200 * 16)) - 1 = 35.18的整数部分,所以UBRDIVn寄存器值为35

    UDIVSLOTn = 0.18 * 16 = 2.88 ≈ 3,即UDIVSLOTn寄存器的值中必须有3个1,为确保串口工作的稳定性,可以根据手册查表得到。

    注意事项:

    ① 当选择PCLK_PSYS为时钟源时,UBRDIVn的值必须 >= 0

    ② 当选择SCLK_UART为时钟源时,计算方法与上文相同,但是UBRDIVn的值可以为0(即在时钟模块已经分频完毕)。当UBRDIVn的值为0时,波特率不受UBRDIVn和UDIVSLOTn寄存器的影响

    3.1.7 UINTMn & UINTSPn & UINTPn

    UINTMn(UART Interrupt Mask)寄存器用于屏蔽指定的中断,当某位置1时即使对应的中断情况发生,也不会触发中断。

    UINTSPn(UART Interrupt Source Pending)寄存器记录了中断源请求的情况,即使在UINTMn寄存器中屏蔽了某个中断,如果该中断发生,依然会将UINTSPn中的对应位置1。

    注意:UINTSPn寄存器只是反映中断源的原始状态,不需要清pend

    UINTPn(UART Interrupt Pending)寄存器是真正的中断源请求寄存器,在UART的ISR中需要清pend;清pend的方式是向对应位写1

    说明:UINTMn/UINTSPn/UINTPn寄存器的关系如下图所示

    3.2 串口初始化&收发数据代码解析

    3.2.1 串口初始化代码解析

    串口初始化代码需要完成以下步骤:

    ① 设置UART对应的GPIO管脚模式

    UART0对应的GPIO管脚由GPA0 group管理

    ② 设置UART模块相关寄存器

    ULCON:8位数据位 + 无奇偶校验 + 1位停止位

    UCON:收发采用中断或轮询模式

    UMCON:禁用modem和AFC相关(使用默认值即可)

    UFCON:暂时不用FIFO(使用默认值即可)

    UFCON/UDIVSLOT:根据波特率计算

    3.2.2 串口收发函数解析

    使用轮询方式实现数据收发,就是不断查询UTRSTATn寄存器对应位的值,并据此执行相关操作。

    说明:

    ① 使用轮询方式实现收发能很好地和printf/scanf函数配合(尤其是在当前没有操作系统的环境下)。

    ② 此处getc函数中没有进行回显,是因为回显实现在了scanf函数中,可参见下文相关内容。

    3.3 基于中断的Rx代码解析

    3.3.1 中断初始化

    中断的整个流程涉及中断源 + VIC + CPU三个部分,

    ① 中断源

    在中断源端使能中断

    ② VIC

    注册ISR + 在VIC端使能中断

    ③ CPU

    为IRQ流程准备环境,包括将CPSR中的I/F位清零、设置IRQ栈、中断源的识别与ISR的调用等

    3.3.2 ISR

    ISR需要完成2个任务,

    ① 实际的中断业务流程

    ② 在中断源端清pend(VIC端清pend由总的中断处理程序完成)

    4. printf移植解析

    4.1 什么是stdio

    ① stdio(standard input output),即标准输入输出

    ② 标准输入输出是操作系统定义的默认的输入和输出通道。一般在PC中,标准输入是键盘,标准输出是屏幕。在操作系统中可以定义标准输入/输出/错误流。

    在我们的程序中,标准输入/输出就是串口。

    ③ printf/scanf函数可以和底层的输入/输出函数绑定,然后这两个函数就可以和stdio绑定起来。

    4.2 C语言对可变参函数的支持

    所需头文件:<stdarg.h>

    <stdarg.h>头文件提供的工具可以使我们能够编写可变数量参数的函数,下面结合示例加以说明。

    运行结果:

    <stdarg.h>提供了1种类型和4个宏用于处理可变参数列表,

    va_list类型:用于处理可变参数列表的类型,在实现中一般就是char *类型

    va_start宏:指出参数列表中可变长度部分开始的位置。带有可变数量参数的函数必须至少有一个"正常的"形式参数,省略号总是出现在形式参数列表的末尾,在最后一个"正常"参数之后。

    实现中就是将参数列表中可变长度部分的起始地址赋值给va_list类型的变量,同时注意4B对齐,具体原因后文会有论述。

    va_end宏:用于对可变参数列表的"清理",实现中可以什么都不做~~

    va_start和va_end宏必须成对调用

    va_arg宏:用于遍历可变参数列表,可以根据指定的类型取出对应的参数。

    其中_bnd宏就是用于实现4B对齐(其实是按int型大小对齐)

    特别注意:每从可变参数列表中取出一个参数,ap会指向下一个参数

    va_copy宏:va_copy(va_list dest, va_list src)在C99中提出,用于拷贝可变参数列表

    va_copy也必须和va_end成对使用

    说明:在可变参数函数中,需要根据"正常"参数解析可变参数列表(e.g. printf函数中的格式字符串)

    特别注意:关于参数类型提升

    当调用带有可变参数列表的函数时,编译器会在省略号对应的所有参数上执行默认的实际参数提升。e.g. char类型和short类型会被提升为int类型,float类型会被提升为double类型。因此把char、short或float类型作为参数传递给va_arg是没有意义的,提升后的参数不可能具有这些类型。

    从实现中分析,从可变参数列表中取出参数时均要求4B对齐,因此在示例中处理字符时也是按int类型取出参数,然后强制类型转换为char类型。

    进阶:深度分析va_start & va_arg宏的实现

    要理解va_start & va_arg宏的工作方式,需要结合函数参数入栈的顺序,参考下图一目了然

    ① va_start宏中,通过&(A)取得的就是形参fmt变量的地址,在示例中就是栈中的0x100地址

    然后在该地址的基础上,就可以计算出可变参数的起始位置,也就是0x104地址

    ② va_arg宏则是根据可变参数的类型,逐个遍历可变参数,此时需要格式字符串标识的类型与实际可变参数的类型一致,否则会解析错误

    ③ 由于va_start & va_arg的运行过程高度依赖参数入栈的顺序(只有函数参数是从右向左入栈时,根据"sdc"字符串的解析才是正确的),这就体现了对编译器设置入栈规范的重要性。

    4.3 移植printf/scanf函数

    4.3.1 移植代码来源

    ① 最原始来源:Linux内核中的printk函数

    ② 简化方法:从uboot中移植(也是从linux中得来)

    ③ 最简单方法:直接使用别人移植好的~~(源自友善之臂裸机代码)

    4.3.2 printf/scanf工程的组织和编译

    将printf/scanf工程相关文件单独编译成静态库供整个工程链接使用,需要注意在CFLAGS变量中添加如下编译选项:

    -nostdinc:不使用标准头文件

    -fno-builtin:不使用内建函数

    在C语言标准中,有些通用函数被定义为built-in function(内建函数),像printf/strchr/memset等等,这些函数不需要包含头文件中的声明,就可以编译链接该函数。增加-fno-builtin选项后,就可以自己实现这些函数,而不会导致冲突。

    -nostdlib:不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。这个选项常用于编译内核、bootloader等程序,它们不需要启动文件、标准库文件。

    4.4 printf/scanf函数工作原理

    4.4.1 printf函数工作原理

    ① 定义发送缓存区g_pcOutBuf

    ② 调用va_start宏取出可变参数列表

    ③ 调用vsprintf函数,根据格式字符串fmt解析可变参数列表,并将解析结果输出到发送缓冲区

    ④ 调用putc函数(此处为串口输出函数)将发送缓冲区中的内容输出到串口

    说明:printf函数调用链

    printf --> vsprintf --> vsnprintf

    在vsnprintf函数中会根据格式字符串解析可变参数列表,并调用va_arg宏逐个取出参数并打印到发送缓存区中。

    4.4.2 scanf函数工作原理

    ① 定义接收缓冲区

    ② 从串口接收数据直到遇到换行(0x0a)或回车(0x0d),此时将接收缓冲区截零(且换行和回车符并不放入接收缓冲区)

    ③ 调用va_start宏取出可变参数列表

    ④ 调用vsscanf函数,根据格式字符串解析可变参数列表,并从g_pcInBuf中取出要赋给变量的值,然后向设定的地址赋值。

    5. 自建bootloader超过BL1长度限制的解决方案

    S5PV210在启动过程中对BL1的长度有16KB的限制,但是随着片内外设使用的增加,尤其是相关库的引入(e.g. printf/scanf),目前自建的bootloader已经超过16KB的限制。

    为实现程序的正确下载/烧写与运行,有如下2种解决方案:

    5.1 dnw下载

    先用dnw下载x210_usb.bin该文件可以完成内存初始化等操作,这样就可以将自建bootloader下载到内存运行。

    注意:经上机验证,通过dnw下载到iRAM中运行的代码可以超过16KB。根据iRAM的内存布局,Reserved部分其实可供自建bootloader下载运行。

    特别注意:重复初始化内存问题

    问题现象:先将x210_usb.bin下载到0xd0020010,再将key_interrupt.bin(自建bootloader)下载到0x20000000,程序没有正确运行。

    原因分析:x210_usb.bin会初始化内存,而自建bootloader中也会初始化一次内存,第二次初始化会使得下载到其中的bootloader失效,所以无法运行。

    解决方案1:直接禁用reset流程中的内存初始化

    经过测试,reset流程中不再调用sdram_asm_init函数初始化内存后,可以将自建bootloader下载到内存中运行(当然,此前要先下载x210_usb.bin运行)。

    需要注意的是,如果下载的内存地址与链接地址(目前为0x20000000)不符,仍需要做重定位。但是要注意其中的一个小限制,为避免异常错误,如果下载地址与链接地址不符,则需要间隔一个bootloader镜像的长度(即需要避免拷贝目标地址与源地址区域的重叠)。

    举个例子,如果自建bootloader链接地址为0x20000000,文件大小为20KB。如果下载地址为0x20000010,会导致异常错误。因为此时重定位相当于把文件整体向前移动16B,而目标地址与源地址区域的重叠会导致拷贝过程中程序就跑飞了~~

    解决方案2:将内存初始化加入code_relocate子过程

    其实这个方案是有逻辑小漏洞的~~需要注意的问题有2个,

    重定位的条件是运行地址和链接地址不匹配;调用sdram_asm_init的条件是内存尚未初始化。

    其中的逻辑漏洞在于,如果此时自建bootloader就是运行在内存中,但是运行地址和链接地址不匹配,此时仍会进行内存初始化,还是会导致问题。也就是说,并不是需要重定位的情况都需要内存初始化。

    解决方法就是,确保自建bootloader的下载地址与链接地址一致

    ② 不能在code_relocate中简单调用bl sdram_asm_init,因为code_relocate为非叶子函数,再次调用bl时,必须将当前LR的内容入栈,否则无法返回code_relocate的上级函数。

    个人:对于自建bootloader大于16KB的情况,建议仍使用dnw下载(SD卡烧写插拔太尼玛麻烦~~)。对于下载x210_usb.bin后下载自建bootloader,建议直接禁用重复的内存初始化即可~~

    5.2 SD卡烧写

    由于mkv210_image.c代码中对BL1镜像限制在16KB,因此可以将自建bootloader工程拆分为2部分。第一部分在16KB以内,第二部分放置剩余部分(存储在SD卡后面的某个扇区中,比如第45个扇区)。然后在第一部分中进行重定位(从SD卡中重定位到内存中,使用S5PV210提供的存储设备操作函数可以完成)。

    BL1的一般任务:

    ① 环境初始化,尤其是内存初始化。

    BL1是由CPU在启动过程中自动从SD卡加载到iRAM中运行,需要为BL2的运行准备环境。

    其实BL2有2个运行场所,如果BL2 < 80KB则可以加载到iRAM中运行;如果BL2 > 80KB则只能加载到内存中运行。

    虽然S5PV210手册中推荐使用iRAM运行BL2,但是Uboot在实现过程中一般直接使用内存运行BL2,我们也采取这种方式。

    ② 将BL2从SD卡加载到内存中并启动运行

    考虑到地址相关操作的影响,BL2的链接地址需要和加载的地址匹配(当然不匹配也可以,就是再在内存中进行一次重定位,但是这么做就木有什么意义了~~)。

    剧透:最终使用的方式,是从完整的自建bootloader中截取出最前端的16KB,而非拆分工程

    展开全文
  • Delphi接口技术开发实例解析 目录 前言 第1章 计算机接口技术  1.1 计算机接口技术概述  1.2 RS-232C串口  1.3 RS-485/422串口  1.4 IEEE-1394串口  1.5 并行端口  1.6 常用外部设备 第2章 Delphi...
  • 而本文介绍通过串口数据传送给单片机,并在单片机上完成数据解析和心电波形LCD显示的功能。 2 通信协议解读 BMD101 通过 UART 接口通信。这是一个标准的 UART 接口,定义为 1 个起始位,8 个数据位,1 停止位格式...
  • 附件内容分享的是基于LabVIEW上位机与串口通信,通过LabVIEW上位机显示波形,在分享其实现的源码同时,分享一段LabVIEW上位机与串口通信工作原理。 基于LabVIEW的串口波形上位机界面展示: 定义通信格式及功能 因为...
  • ThinkGear 通信协议英文

    2018-01-20 22:03:39
    MindSet 通信协议,详细的定义了如何 MindSet 通信。我们可以这样描述在通信中,我们 需要解决的问题: 1、怎样连接蓝牙串口,接收数据流 2、如何解析数据流,把每一帧的数据解析出来 3、如何解析每帧数据,从而...
  • 内容包括开发windows ce的bootloader、oal、显示设备驱动程序、串口驱动程序和pc卡总线接口驱动程序,通过解析和研读微软的deviceemulator开发板的bsp的源代码,旨在帮助读者系统、全面、具体地了解windows embedded...
  • Windows CE工程实践完全解析(pdf)

    热门讨论 2011-11-12 18:59:56
    内容包括开发windows ce的bootloader、oal、显示设备驱动程序、串口驱动程序和pc卡总线接口驱动程序,通过解析和研读微软的deviceemulator开发板的bsp的源代码,旨在帮助读者系统、全面、具体地了解windows embedded...
  • 第7章 Modem/串口通信编程实例 353 7.1 AT命令 353 7.1.1 Modem状态 353 7.1.2 AT命令 354 7.1.3 Modem返回信息码 354 7.2 MSCOMM控件编程实例 355 7.2.1 实现原理 355 7.2.2 实例实现 356 7.3 ...
  • 基于VC++6.0的高速串口通信数据采集系统.pdf 基于VC++变电站自动化系统监控软件的研究实现.pdf 基于VC++和LabVIEW技术的虚拟示波器的设计实现.pdf 基于VC++和MATLAB的车型分类及车辆计数系统.pdf 基于VC++的AIS...
  • 基于VC++6.0的高速串口通信数据采集系统.pdf 基于VC++变电站自动化系统监控软件的研究实现.pdf 基于VC++和LabVIEW技术的虚拟示波器的设计实现.pdf 基于VC++和MATLAB的车型分类及车辆计数系统.pdf 基于VC++的AIS...
  • 386 8.1.2 实例实现 388 8.2 HTTP代理服务器实例 397 8.2.1 主框架代码分析 397 8.2.2 代理类CProxyServer的实现 399 <br>第9章 高级实例解析 409 9.1 串口通信高级编程实例 ...
  • 386 8.1.2 实例实现 388 8.2 HTTP代理服务器实例 397 8.2.1 主框架代码分析 397 8.2.2 代理类CProxyServer的实现 399 <br>第9章 高级实例解析 409 9.1 串口通信高级编程实例 ...
  • 386 8.1.2 实例实现 388 8.2 HTTP代理服务器实例 397 8.2.1 主框架代码分析 397 8.2.2 代理类CProxyServer的实现 399 <br>第9章 高级实例解析 409 9.1 串口通信高级编程实例 ...
  • 描述了GPS手持终端串口通信的方法,并在WinCE6.0操作系统下提取GPS的定位信息,采用NMEA-0183通信协议中的RMC数据格式进行解析。简述了GIS概念,并介绍了GPS在GIS方面的应用。
  • 基于VC++6.0的高速串口通信数据采集系统.pdf 基于VC++变电站自动化系统监控软件的研究实现.pdf 基于VC++和LabVIEW技术的虚拟示波器的设计实现.pdf 基于VC++和MATLAB的车型分类及车辆计数系统.pdf 基于VC++的AIS...
  • 基于VC++6.0的高速串口通信数据采集系统.pdf 基于VC++变电站自动化系统监控软件的研究实现.pdf 基于VC++和LabVIEW技术的虚拟示波器的设计实现.pdf 基于VC++和MATLAB的车型分类及车辆计数系统.pdf 基于VC++的AIS...
  • 386 8.1.2 实例实现 388 8.2 HTTP代理服务器实例 397 8.2.1 主框架代码分析 397 8.2.2 代理类CProxyServer的实现 399 <br>第9章 高级实例解析 409 9.1 串口通信高级编程实例 ...
  • 说明:通过AXI Uartlite IP核实现FPGAPC的串口通信。 环境:Vivado2018.3。 IP核:AXI Uartlite(2.0)。 参考手册:pg142-axi-uartlite。 AXI协议资料:AXI 文章目录1.串口通信协议1.1基础知识:1.2串口传输格式1.3...
  • 上两篇博文整理学习了有关串口通信、串口编程以及GPS数据格式的一些基本知识。本篇我们要开始编程实现GPS自动定位数据解析。我们将在FL2440开发板上实现该功能。 由于SF2820模块获取到的GPS定位信息是通过串口发送...
  • 12.3.2 完整的HCI操作过程与解析275 12.3.3 蓝牙串口通信编程示例287 12.4 CSR蓝牙鼠标示例设计295 12.5 CSR蓝牙无线耳机示例设计312 12.6 蓝牙打印机设计原理328 12.7 BlueCore蓝牙芯片的接口设计与实现331 12.8 ...
  • JSON数据也许大家都很陌生,而对我来讲属于半成品,由于项目问题,做web虽然用的是JSON数据格式传输,但是关于解析这一块还真不知道该注意什么,更不知道它是如何解析的,由于最近要把串口通信协议此一致,所以,...
  • JSON数据也许大家都很陌生,而对我来讲属于半成品,由于项目问题,做web虽然用的是JSON数据格式传输,但是关于解析这一块还真不知道该注意什么,更不知道它是如何解析的,由于最近要把串口通信协议此一致,所以,...
  • ZigBee2007PRO协议栈实验实践.pdf

    热门讨论 2014-12-24 23:49:08
    4.6.2 ZigBee数据格式122 4.6.3 加入网络数据分析125 4.6.4 收发数据分析126 4.7 实验效果128 第5章 ZigBee无线网络开发进阶 5.1 ZigBee协议栈结构129 5.2 ZigBee协议栈实时操作系统132 5.2.1 OS术语介绍132 ...
  • uart2any v1.32

    2013-06-18 14:24:34
    Uart2Can 串口调试可支持U2clrs的RS232接口、RS485接口、LIN总线、38kHz红外通信等接口的调试; Uart2any支持对U2clrs的基于串口的Can总线转换器的调试;可设置Can转换器波特率、滤波器模式及滤波器ID、发送指定ID...
  • WarThunder数据解析任务负责解析来自PC串口通信的飞行数据,TouchGFX UI任务负责显示数据,Main任务中循环blink板载LED 软件模块说明WarThunder数据解析任务 简单的string.h 解析,自定义格式帧 TouchGFX UI任务均由...

空空如也

空空如也

1 2 3 4 5
收藏数 81
精华内容 32
关键字:

串口通信数据格式与解析