通用挽联
USART篇(一):STM32 USART通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和I
USART

USART篇(一):STM32 USART


通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分
数波特率发生器提供宽范围的波特率选择。
它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR
ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。 使用多缓冲器配置的DMA方式,可以实现高速数据通信。
[编辑] USART主要特性
● 全双工的,异步通信
● NRZ标准格式
● 分数波特率发生器系统
─ 发送和接收共用的可编程波特率,最高达 4.5Mbits/s
● 可编程数据字长度(8位或9位)
● 可配置的停止位-支持1或2个停止位
● LIN主发送同步断开符的能力以及LIN从检测断开符的能力
─ 当 USART硬件配置成 LIN时,生成13位断开符;检测 10/11位断开符
● 发送方为同步传输提供时钟
● IRDA SIR 编码器解码器
─ 在正常模式下支持 3/16位的持续时间
● 智能卡模拟功能
─ 智能卡接口支持 ISO7816-3标准里定义的异步智能卡协议
─ 智能卡用到的 0.5和 1.5个停止位
● 单线半双工通信
● 可配置的使用DMA的多缓冲器通信
─ 在 SRAM里利用集中式 DMA缓冲接收/发送字节
● 单独的发送器和接收器使能位
● 检测标志
─ 接收缓冲器满
─ 发送缓冲器空
─ 传输结束标志
● 校验控制
─ 发送校验位
─ 对接收数据进行校验
● 四个错误检测标志
─ 溢出错误
─ 噪音错误
─ 帧错误
─ 校验错误
● 10个带标志的中断源
─ CTS改变
─ LIN断开符检测
─ 发送数据寄存器空
─ 发送完成
─ 接收数据寄存器满
─ 检测到总线为空闲
─ 溢出错误
─ 帧错误
─ 噪音错误
─ 校验错误
● 多处理器通信 -- 如果地址不匹配,则进入静默模式
● 从静默模式中唤醒(通过空闲总线检测或地址标志检测)
● 两种唤醒接收器的方式:地址位(MSB,第9位),总线空闲
[编辑] USART功能概述
接口通过三个引脚与其他设备连接在一起(见图236)。任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。
RX:接收数据串行输。通过过采样技术来区别数据和噪音,从而恢复数据。
TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。
● 总线在发送或接收前应处于空闲状态
● 一个起始位
● 一个数据字(8或9位),最低有效位在前
● 0.5,1.5,2个的停止位,由此表明数据帧的结束
● 使用分数波特率发生器 —— 12位整数和4位小数的表示方法。
● 一个状态寄存器(USART_SR)
● 数据寄存器(USART_DR)
● 一个波特率寄存器(USART_BRR),12位的整数和4位小数
● 一个智能卡模式下的保护时间寄存器(USART_GTPR)
关于以上寄存器中每个位的具体定义,请参考寄存器描述0节。
在同步模式中需要下列引脚:
● SCLK:发送器时钟输出。此引脚输出用于同步传输的 时钟,
(在Start位和Stop位上没有时钟脉冲,软件可选地,可以在最后一个数据位送出一个时钟脉冲)。数据可以在RX上同步被接收。这可以用来控制带有移
位寄存器的外部设备(例如LCD驱动器)。时钟相位和极性都是软件可编程的。在智能卡模式里,SCLK可以为智能卡提供时钟。
在IrDA模式里需要下列引脚:
● IrDA_RDI: IrDA模式下的数据输入。
● IrDA_TDO: IrDA模式下的数据输出。
下列引脚在硬件流控模式中需要:
● nCTS: 清除发送,若是高电平,在当前数据传输结束时阻断下一次的数据发送。
● nRTS: 发送请求,若是低电平,表明USART准备好接收数据
[编辑] USART 特性描述
字长可以通过编程USART_CR1寄存器中的M位,选择成8或9位(见0)。在起始位期间,TX脚处于低电平,在停止位期间处于高电平。 空闲符号被视为完全由’1’组成的一个完整的数据帧,后面跟着包含了数据的下一帧的开始位(‘1’的位数也包括了停止位的位数)。
断开符号被视为在一个帧周期内全部收到’0’(包括停止位期间,也是’0’)。在断开帧结束时,发送器再插入1或2个停止位(‘1’)来应答起始位。
发送和接收由一共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟。
随后将有每个功能块的详细说明。
[编辑] 发送器
发送器根据M位的状态发送8位或9位的数据字。当发送使能位(TE)被设置时,发送移位寄存器中的数据在TX脚上输出,相应的时钟脉冲在SCLK脚上输出。
[编辑] 字符发送
在USART发送期间,在TX引脚上首先移出数据的最低有效位。在此模式里,USART_DR寄存器包含了一个内部总线和发送移位寄存器之间的缓冲器(见图236)。 每个字符之前都有一个低电平的起始位;之后跟着的停止位,其数目可配置。 注意:1.在数据传输期间不能复位TE位,否则将破坏TX脚上的数据,因为波特率计数器停止计数。正在传输的当前数据将丢失。 2. TE位被激活后将发送一个空闲帧。
[编辑] 可配置的停止位
随每个字符发送的停止位的位数可以通过控制寄存器2的位13、12进行编程。
1. 1个停止位:停止位位数的默认值。
2. 2个停止位:可用于常规USART模式、单线模式以及调制解调器模式。
3. 0.5个停止位:在智能卡模式下接收数据时使用。
4. 1.5个停止位:在智能卡模式下发送数据时使用。
空闲帧包括了停止位。
断开帧是10位低电平,后跟停止位(当m=0时);或者11位低电平,后跟停止位(m=1时)。不可能传输更长的断开帧(长度大于10或者11位)。
配置步骤:
1. 通过在USART_CR1寄存器上置位UE位来激活USART。
2. 编程USART_CR1的M位来定义字长。
3. 在USART_CR2中编程停止位的位数。
4. 如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中的描述配置DMA寄存器。
5. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
6. 利用USART_BRR寄存器选择要求的波特率。
7. 把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。
[编辑] 单字节通信
清零TXE位总是通过对数据寄存器的写操作来完成的。TXE位由硬件来设置,它表明:
● 数据已经从TDR移送到移位寄存器,数据发送已经开始
● TDR寄存器被清空
● 下一个数据可以被写进USART_DR寄存器而不会覆盖先前的数据
如果TXEIE位被设置,此标志将产生一个中断。
如果此时USART正在发送数据,对USART_DR寄存器的写操作把数据存进TDR寄存器,并在当前传输结束时把该数据复制进移位寄存器。
如果此时USART没有在发送数据,处于空闲状态,对USART_DR寄存器的写操作直接把数据放进移位寄存器,数据传输开始,TXE位立即被置起。当一帧发送完成时(停止位发送后),TC位被置起,并且如果USART_CR1寄存器中的TCIE位被置起时,中断产生。
先读一下USART_SR寄存器,再写一下USART_DR寄存器,可以完成对TC位的清零。注意: TC位也可以通过对它软件写’0’来清除。此清零方式只在多缓冲器通信模式下推荐使用。
[编辑] 断开符号
设置SBK可发送一个断开符号。断开帧长度取决M位(见0)。如果设置SBK=1,在完成当前数据发送后,将在TX线上发送一个断开符号。断开字符
发送完成时(在断开符号的停止位时)SBK被硬件复位。USART在最后一个断开帧的结束处插入一逻辑’1’,以保证能识别下一帧的起始位。注意:如果在开始发送断开帧之前,软件又复位了SBK位,断开符号将不被发送。如果要发送两个连续的断开帧,SBK位应该在前一个断开符号的停止位之后置起。
[编辑] 空闲符号
置位TE将使得USART在第一个数据帧前发送一空闲帧。
[编辑] 接收器
USART可以根据USART_CR1的M位接收8位或9位的数据字。
[编辑] 起始位侦测
在USART中,如果辨认出一个特殊的采样序列,那么就认为侦测到一个起始位。 该序列为:1110X0X0X0X0X0X0 。注意: 如果该序列不完整,那么接收端将退出起始位侦测并回到空闲状态(不设置标志位)等待下降沿。
如果3个采样点上仅有2个是零(第3、第5和第7个采样点或者第8、第9和第10个采样点),那么起始位仍然是有效的,但是会设置NE噪声标志位。
如果最后三个(第8、第9和第10)采样点为0,那么起始位将被确认。
[编辑] 字符接收
在USART接收期间,数据的最低有效位首先从RX脚移进。在此模式里,USART_DR寄存器包含的缓冲器位于内部总线和接收移位寄存器之间。
配置步骤:
1. 将USART_CR1寄存器的UE置1来激活USART。
2. 编程USART_CR1的M位定义字长
3. 在USART_CR2中编写停止位的个数
4. 如果需多缓冲器通信,选择USART_CR3中的DMA使能位(DMAR)。按多缓冲器通信所要求的配置DMA寄存器。
5. 利用波特率寄存器USART_BRR选择希望的波特率。
6. 设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。
当一字符被接收到时,
● RXNE位被置位。它表明移位寄存器的内容被转移到RDR。换句话说,数据已经被接收并且可以被读出(包括与之有关的错误标志)。
● 如果RXNEIE位被设置,产生中断。
● 在接收期间如果检测到帧错误,噪音或溢出错误,错误标志将被置起。
● 在多缓冲器通信时,RXNE在每个字节接收后被置起,并由DMA对数据寄存器的读操作而清零。
● 在单缓冲器模式里,由软件读USART_DR寄存器完成对RXNE位清除。RXNE标志也可以通过对它写0来清除。RXNE位必须在下一字符接收结束前被清零,以避免溢出错误。 注意:在接收数据时,RE位不应该被复位。如果RE位在接收时被清零,当前字节的接收被丢失。
[编辑] 断开符号
当接收到一个断开帧时,USART像处理帧错误一样处理它。
[编辑] 空闲符号
当一空闲帧被检测到时,其处理步骤和接收到普通数据帧一样,但如果IDLEIE位被设置将产生一个中断。
[编辑] 溢出错误
如果RXNE还没有被复位,又接收到一个字符,则发生溢出错误。数据只有当RXNE位被清零后才能从移位寄存器转移到RDR寄存器。RXNE标记是接收到每个字节后被置位的。如果下一个数据已被收到或先前DMA请求还没被服务时,RXNE标志仍是置起的,溢出错误产生。
当溢出错误产生时:
● ORE位被置位。
● RDR内容将不会丢失。读USART_DR寄存器仍能得到先前的数据。
● 移位寄存器中以前的内容将被覆盖。随后接收到的数据都将丢失。
● 如果RXNEIE位被设置或EIE和DMAR位都被设置,中断产生。
● 顺序执行对USART_SR和USART_DR寄存器的读操作,可复位ORE位 注意: 当ORE位置位时,表明至少有1个数据已经丢失。有两种可能性:
● 如果RXNE=1,上一个有效数据还在接收寄存器RDR上,可以被读出。

如果RXNE=0,这意味着上一个有效数据已经被读走,RDR已经没有东西可读。当上一个有效数据在RDR中被读取的同时又接收到新的(也就是丢失的)数
据时,此种情况可能发生。在读序列期间(在USART_SR寄存器读访问和USART_DR读访问之间)接收到新的数据,此种情况也可能发生。
[编辑] 噪音错误
使用过采样技术(同步模式除外),通过区别有效输入数据和噪音来进行数据恢复。
当在接收帧中检测到噪音时:
● NE在RXNE位的上升沿被置起。
● 无效数据从移位寄存器移送到USART_DR寄存器。
● 在单个字节通信情况下,没有中断产生。然而,NE这个位和RXNE位同时置起,后者自己产生中断。在多缓冲器通信情况下,如果USART_CR3寄存器中EIE位被置位的话,将产生一中断。
顺序执行对USART_SR和USART_DR寄存器的读操作,可复位NE位。
[编辑] 帧错误
当以下情况发生时检测到帧错误:
由于没有同步上或大量噪音的原因,停止位没有在预期的时间上接和收识别出来。
当帧错误被检测到时:
● FE位被硬件置起
● 无效数据从移位寄存器传送到USART_DR寄存器。
● 在单字节通信时,没有中断产生。然而,这个位和RXNE位同时置起,后者将产生中断。在多缓冲器通信情况下,如果USART_CR3寄存器中EIE位被置位的话,将产生中断。
顺序执行对USART_SR和USART_DR寄存器的读操作,可复位FE位。
[编辑] 接收期间的可配置的停止位
被接收的停止位的个数可以通过控制寄存器2的控制位来配置,在正常模式时,可以是1或2个,在智能卡模式里可能是0.5或1.5个。
1. 0.5个停止位(智能卡模式里的接收):不对0.5个停止位进行采样。因此,如果选择0.5个停止位则不能检测帧错误和断开帧。
2. 1个停止位:对1个停止位的采样在第8,第9和第10采样点上进行。
3. 1.5
个停止位(智能卡模式里的发送):当以智能卡模式发送时,器件必须检查数据是否被正确的发送出去。所以接收器功能块必须被激活(USART_CR1寄存器
中的RE
=1),并且在停止位的发送期间采样数据线上的信号。如果出现校验错误,智能卡会在发送方采样NACK信号时,即总线上停止位对应的时间内时,拉低数据
线,以此表示出现了帧错误。FE在1.5个停止位结束时和RXNE一起被置起。对1.5个停止位的采样是在第16,第17和第18采样点进行的。1.5个
的停止位可以被分成2部分:一个是0.5个时钟周期,期间不做任何事情 。随后是1个时钟周期的停止位,在这段时间的中点处采样。
4. 2个停止位:对2个停止位的采样是在第一停止位的第8,第9和第10个采样点完成的。如果第一个停止位期间检测到一个帧错误,帧错误标志将被设置。第二个停止位不再检查帧错误。在第一个停止位结束时RXNE标志将被设置。
[编辑] 分数波特率的产生
接收器和发送器的波特率在USARTDIV的整数和小数寄存器中的值应设置成相同。
Tx/Rx波特率= fPCLKx/(16*USARTDIV)
这里的fPCLKx(x=1、2)是给外设的时钟(PCLK1用于USART2、3、4、5,PCLK2用于USART1) USARTDIV是一个无符号的定点数。这12位的值设置在USART_BRR寄存器。
[编辑] 如何从USART_BRR寄存器值得到USARTDIV
例1:
如果 DIV_Mantissa = 27d , DIV_Fraction = 12d (USART_BRR=1BCh),
于是
Mantissa (USARTDIV) = 27d
Fraction (USARTDIV) = 12/16 = 0.75d
所以 USARTDIV = 27.75d 例2:
要求 USARTDIV = 25.62d,
就有:
DIV_Fraction = 16*0.62d = 9.92d, 近似等于10d = 0x0A
DIV_Mantissa = mantissa (25.620d) = 25d = 0x19
于是, USART_BRR = 0x19A例3:
要求 USARTDIV = 50.99d
就有:
DIV_Fraction = 16*0.99d = 15.84d =>近似等于16d = 0x10
DIV_Mantissa = mantissa (50.990d) = 50d = 0x32注意: 更新波特率寄存器USART_BRR后,波特率计数器中的值也立刻随之更新。所以在通信进行时不应改变USART_BRR中的值。注:
1. CPU的时钟频率越低某一特定波特率的误差也越低2. 只有USART1使用PCLK2(最高72MHz)。其它USART使用PCLK1(最高36MHz)。
[编辑] 多处理器通信
通过USART可以实现多处理器通信(将几个USART连在一个网络里)。例如某个USART设备可以是主,它的TX输出和其他USART从设备的RX输入相连接;USART从设备各自的TX输出逻辑地与在一起,并且和主设备的RX输入相连接。
在多处理器配置中,我们通常希望只有被寻址的接收者才被激活,来接收随后的数据,这样就可以减少由未被寻址的接收器的参与带来的多余的USART服务开销。
未被寻址的设备可启用其静默功能置于静默模式。在静默模式里:
● 任何接收状态位都不会被设置。
● 所有接收中断被禁止。
● USART_CR1寄存器中的RWU位被置1。RWU可以被硬件自动控制或在某个条件下由软件写入。
根据USART_CR1寄存器中的WAKE位状态,USART可以用二种方法进入或退出静默模式。
● 如果WAKE位被复位:进行空闲总线检测。
● 如果WAKE位被设置:进行地址标记检测。
[编辑] 空闲总线检测(WAKE=0)
当RWU位被写1时,USART进入静默模式。当检测到一空闲帧时,它被唤醒。然后RWU被硬件清零,但是USART_SR寄存器中的IDLE位并不置起。RWU还可以被软件写0。图241给出利用空闲总线检测来唤醒和进入静默模式的一个例子:
[编辑] 地址标记(address mark)检测(WAKE=1)
在这个模式里,如果MSB是1,该字节被认为是地址,否则被认为是数据。在一个地址字节中,目标接收器的地址被放在4个LSB中。这个4位地址被接收器同它自己地址做比较,接收器的地址被编程在USART_CR2寄存器的ADD。
如果接收到的字节与它的编程地址不匹配时,USART进入静默模式。该字节的接收既不会置起RXNE标志也不会产生中断或发出DMA请求,因为USART已经在静默模式。
当接收到的字节与接收器内编程地址匹配时,USART退出静默模式。然后RWU位被清零,随后的字节被正常接收。匹配的地址字节将置位RXNE位,因为RWU位已被清零。
当接收缓冲器不包含数据时(USART_SR的RXNE=0),RWU位可以被写0或1。否则,该次写操作被忽略。图242给出利用地址标记检测来唤醒和进入静默模式的例子。
[编辑] 校验控制
奇偶控制(发送时生成一个奇偶位,接收时进行奇偶校验)可以通过设置USART_CR1寄存器上的PCE位而激活。根据M位定义的帧长度,可能的USART帧格式列在表155中。
在用地址标记唤醒设备时,地址的匹配只考虑到数据的MSB位,而不用关心校验位。(MSB是数据位中最后发出的,后面紧跟校验位或者停止位)偶校验:校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为偶数。
例如:数据=00110101,有4个’1’,如果选择偶校验(在USART_CR1中的PS=0),校验位将是’0’。 奇校验:此校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为奇数。
例如:数据=00110101,有4个’1’,如果选择奇校验(在USART_CR1中的PS=1),校验位将是’1’。传输模式:如果USART_CR1的PCE位被置位,写进数据寄存器的数据的MSB位被校验位替换后发送出去(如果选择偶校验偶数
个’1’,如果选择奇校验奇数个’1’)。如果奇偶校验失败,USART_SR寄存器中的PE标志被置’1’,并且如果USART_CR1寄存器的
PEIE在被预先设置的话,中断产生。
[编辑] LIN(局域互联网)模式
LIN模式是通过设置USART_CR2寄存器的LINEN位选择。在LIN模式下,下列位必须保持为0:
● USART_CR2寄存器的CLKEN位
● USART_CR3寄存器的STOP[1:0],SCEN,HDSEL和IREN
[编辑] LIN发送
LIN发送和正常USART发送有以下区别:
● 清零M位以配置8位字长
● 置位LINEN位以进入LIN模式。这时,置位SBK将发送13位’0’作为断开符号。然后发一位’1’,以允许对下一个开始位的检测。
[编辑] LIN接收
当LIN模式被使能时,断开符号检测电路被激活。该检测完全独立于USART接收器。断开符号只要一出现就能检测到,不管是在总线空闲时还是在发送某数据帧其间,数据帧还未完成,又插入了断开符号的发送。
当接收器被激活时(USART_CR1的RE=1),电路监测RX上的起始信号。监测起始位的方法同检测断开符号或数据是一样的。当起始位被检测到后,电
路对每个接下来的位,在每个位的第8,9,10个过采样时钟点上进行采样。如果10个(当USART_CR2 的LBDL =
0)或11个(当USART_CR2 的LBDL =
1)连续位都是’0’,并且又跟着一个定界符,USART_SR的LBD标志被设置。如果LBDIE位=1,中断产生。在确认断开符号前,要检查定界符,
因为它意味RX线已经回到高电平。
如果在第10或11个采样点之前采样到了’1’,检测电路取消当前检测并重新寻找起始位。如果LIN模式被禁止,接收器继续如正常USART那样工作,不需要考虑检测断开符号。
如果LIN模式没有被激活(LINEN=0),接收器仍然正常工作于USART模式,不会进行断开检测。
如果LIN模式被激活(LINEN=1),只要一发生帧错误(也就是停止位检测到’0’,这种情况出现在断开帧),接收器就停止,直到断开符号检测电路接
收到一个’1’(这种情况发生于断开符号没有完整的发出来),或一个定界符(这种情况发生于已经检测到一个完整的断开符号)。
图243说明了断开符号检测器状态机的行为和断开符号标志的关系。
图244给了一个断开帧的例子。
[编辑] USART 同步模式
通过在USART_CR2寄存器上写CLKEN位选择同步模式 。
在同步模式里,下列位必须保持清零状态:
● USART_CR2寄存器中的LINEN位
● USART_CR3寄存器中的SCEN,HDSEL和IREN位
USART允许用户以主模式方式控制双向同步串行通信。SCLK脚是USART发送器时钟的输出。在起始位和停止位期间,SCLK脚上没有时钟脉冲。根据
USART_CR2寄存器中LBCL位的状态,决定在最后一个有效数据位期间产生或不产生时钟脉冲。USART_CR2寄存器的CPOL位允许用户选择时
钟极性,USART_CR2寄存器上的CPHA位允许用户选择外部时钟的相位(见图245、图246和图247)。
在总线空闲期间,实际数据到来之前以及发送断开符号的时候,外部SCLK时钟不被激活。
同步模式时,USART发送器和异步模式里工作一模一样。但是因为SCLK是与TX同步的(根据CPOL和CPHA),所以TX上的数据是随SCLK同步发出的。
同步模式的USART接收器工作方式与异步模式不同。如果RE=1,数据在SCLK上采样(根CPOL和CPHA决定在上升沿还是下降沿),不需要任何的过采样。但必须考虑建立时间和持续时间(取决于波特率,1/16位时间)。注意:1.SCLK脚同TX脚一起联合工作。因而,只有在发送器被激活(TE=1),且数据被发送时(USART_DR寄存器被写入)才提供时钟。这意味着在没有发送数据时是不可能接收一个同步数据的。2.LBCL,CPOL和CPHA位的正确配置,应该在发送器和接收器都被禁止时;当发送器或接收器被激活时,这些位不能被改变。3.建议在同一条指令中设置TE和RE,以减少接收器的建立时间和保持时间。4. USART只支持主模式:它不能用来自其他设备的输入时钟接收或发送数据(SCLK永远是输出)。注: 在智能卡模式下SCLK的功能不同,有关细节请参考智能卡模式部分。
[编辑] 单线半双工通信
单线半双方模式通过设置USART_CR3寄存器的HDSEL位选择。在这个模式里,下面的位必须保持清零状态:
● USART_CR2寄存器的LINEN和CLKEN位
● USART_CR3寄存器的SCEN和IREN位
USART可以配置成遵循单线半双工协议。使用控制位“HALF DUPLEX SEL”选择半双工和全双工通信。当HDSEL写’1’时
● RX不再被使用
● 当没有数据传输时,TX总是被释放。因此,它在空闲状态的或接收状态时表现为一个标准I/O口。这就意味该I/O在不被USART驱动时,必须配置成悬空输入(或开漏的输出高)。
除此以外,通信与正常USART模式类似。由软件来管理线上的冲突(例如通过使用一个中央仲裁器)。特别的是,发送从不会被硬件所阻碍。当TE位被设置时,只要数据一写到数据寄存器上,发送就继续。
[编辑] 智能卡
设置USART_CR3寄存器的SCEN位选择智能卡模式。在智能卡模式下,下列位必须保持清零:
● USART_CR2寄存器的LINEN位
● USART_CR3寄存器的HDSEL 位和IREN位
此外,CLKEN位可以被设置,以提供时钟给智能卡。智能卡接口设计成ISO7816-3标准所定义的那样支持异步协议的智能卡。USART应该被设置为:
● 8位数据位加校验位: 此时USART_CR1寄存器M=1,PCE=1,并且下列条件满足其一:
─ 接收时 0.5个停止位:即 USART_CR2寄存器的 STOP=01
─ 发送时 1.5个停止位:即 USART_CR2寄存器的 STOP=11
图249给出的例子说明了数据线上,在有校验错误和没校验错误两种情况下的信号。
当与智能卡相连接时,USART的TX驱动一根智能卡也驱动的双向线。为了做到这点,SW_RX必须和TX连接到相同的I/O口。在发送开始位和数据字节
期间,发送器的输出使能位TX_EN被置起,在发送停止位期间被释放(弱上拉),因此在发现校验错误的情况下接收器可以将数据线拉低。如果TX_EN不被
使用,在停止位期间TX被拉到高电平:这样的话,只要TX配置成开漏,接收器也可以驱动这根线。
智能卡是一个单线半双工通信协议
● 从发送移位寄存器把数据发送出去,要被延时最小1/2波特时钟。在正常操作时,一个满的发送移位寄存器将在下一个波特时钟沿开始向外移出数据。在智能卡模式里,此发送被延迟1/2波特时钟。

如果在接收数据帧期间,检测到一校验错误,该帧接收完成后(也就是在0.5停止位结束时),发送线被拉低一个波特时钟周期。这是告诉智能卡发送到
USART的数据没有被正确接收到。此NACK信号(拉低发送线一个波特时钟周期)在发送端将产生一个帧错误(发送端被配置成1.5个停止位)。应用程序
可以根据协议处理重新发送的数据。如果NACK控制位被设置,发生校验错误时接收器会给出一个NACK信号;否则就不会发送NACK。

TC标志的置起可以通过编程保护时间寄存器得以延时。在正常操作时,当发送移位寄存器变空并且没有新的发送请求出现时,TC被置起。在智能卡模式里,空的
发送移位寄存器将触发保护时间计数器开始向上计数,直到保护时间寄存器中的值。TC在这段时间被强制拉低。当保护时间计数器达到保护时间寄存器中的值
时,TC被置高。
● TC标志的撤销不受智能卡模式的影响。
● 如果发送器检测到一个帧错误(收到接收器的NACK信号),发送器的接收功能模块不会把NACK当作起始位检测。根据ISO协议,接收到的NACK的持续时间可以是1或2波特时钟周期。
● 在接收器这边,如果一个校验错误被检测到,并且NACK被发送,接收器不会把NACK检测成起始位。注意:
1. 断开符号在智能卡模式里没有意义。一个带帧错误的00h数据将被当成数据而不是断开符号。2. 当来回切换TE位时,没有IDLE帧被发送。ISO协议没有定义IDLE帧。
图250详述了USART是如何采样NACK信号的。在这个例子里,USART正在发送数据,并且被配置成1.5个停止位。为了检查数据的完整性和NACK信号,USART的接收功能块被激活。
USART可以通过SCLK输出为智能卡提供时钟。在智能卡模式里,SCLK不和通信直接关联,而是先通过一个5位预分频器简单地用内部的外设输入时钟来
驱动智能卡的时钟。分频率在预分频寄存器USART_GTPR中配置。SCLK频率可以从fCK/2到fCK/62,这里的fCK是外设输入时钟。
[编辑] IrDA SIR ENDEC 功能块
通过设置USART_CR3寄存器的IREN位选择IrDA模式。在IRDA模式里,下列位必须保持清零:
● USART_CR2寄存器的LINEN,STOP和CLKEN位
● USART_CR3寄存器的SCEN和HDSEL位。
IrDA
SIR物理层规定使用反相归零调制方案(RZI),该方案用一个红外光脉冲代表逻辑’0’(见图251)。SIR发送编码器对从USART输出的
NRZ(非归零)比特流进行调制。输出脉冲流被传送到一个外部输出驱动器和红外LED。USART为SIR
ENDEC最高只支持到115.2Kbps速率。在正常模式里,脉冲宽度规定为一个位周期的3/16。
SIR接收解码器对来自红外接收器的归零位比特流进行解调,并将接收到的NRZ串行比特流输出到USART。在空闲状态里,解码器输入通常是高(标记状态marking state)。发送编码器输出的极性和解码器的输入相反。当解码器输入低时,检测到一个起始位。

IrDA是一个半双工通信协议。如果发送器忙(也就是USART正在送数据给IrDA编码器),IrDA接收线上的任何数据将被IrDA解码器忽视。如果
接收器忙(也就是USART正在接收从IrDA解码器来的解码数据),从USART到IrDA的TX上的数据将不会被IrDA编码。当接收数据时,应该避
免发送,因为将被发送的数据可能被破坏。
● SIR发送逻辑把’0’作为高脉冲发送,把’1’作为低电平发送。脉冲的宽度规定为正常模式时位周期的3/16(见图252)。
● SIR接收逻辑把高电平状态解释为’1’,把低脉冲解释为’0’。
● 发送编码器输出与解码器输入有着相反的极性。当空闲时,SIR输出处于低状态。
● SIR解码器把IrDA兼容的接收信号转变成给USART的比特流。

IrDA规范要求脉冲要宽于1.41us。脉冲宽度是可编程的。接收器端的尖峰脉冲检测逻辑滤除宽度小于2个PSC周期的脉冲(PSC是在IrDA低功耗
波特率寄存器USART_GTPR中编程的预分频值)。宽度小于1个PSC周期的脉冲一定被滤除掉,但是那些宽度大于1个而小于2个PSC周期的脉冲可能
被接收或滤除,那些宽度大于2个周期的将被视为一个有效的脉冲。当PSC=0时,IrDA编码器/解码器不工作。
● 接收器可以与一低功耗发送器通信。
● 在IrDA模式里,USART_CR2寄存器上的STOP位必须配置成1个停止位。
[编辑] IrDA低功耗模式
发送器
在低功耗模式,脉冲宽度不再持续3/16个位周期。取而代之,脉冲的宽度是低功耗波特率的3倍,它最小可以是1.42MHz。通常这个值是
1.8432MHz(1.42 MHz < PSC < 2.12 MHz)。一个低功耗模式可编程分频器把系统时钟进行分频以达到这个值。接收器
低功耗模式的接收类似于正常模式的接收。为了滤除尖峰干扰脉冲,USART应该滤除宽度短于1个PSC的脉冲。只有持续时间大于2个周期的IrDA低功耗波特率时钟(USART_GTPR中的PSC)的低电平信号才被接受为有效的信号。
1. 宽度小于2个大于1个PSC周期的脉冲可能会也可能不会被滤除。
2. 接收器的建立时间应该由软件管理。IrDA物理层技术规范规定了在发送和接收之间最小要有10ms的延时(IrDA是一个半双工协议)。
[编辑] 利用DMA连续通信
USART可以利用DMA连续通信。Rx缓冲器和Tx缓冲器的DMA请求是分别产生的。注意: 参考产品技术说明以确定是否可用DMA控制器。如果所用产品无DMA功能,应使用USART。在USART2_SR寄存器里,可以清零TXE/RXNE标志来实现连续通信。
[编辑] 利用DMA发送
使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激活。只要TXE位被置起,就从配置成使用DMA外设的SRAM区装载数据到USART_DR寄存器。为USART的发送分配一个DMA通道的步骤如下(x表示通道号):
1. 在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事件后,数据将被传送到这个地址。
2. 在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,数据将从此存储器区传送到USART_DR寄存器。
3. 在DMA控制寄存器中配置要传输的总的字节数。
4. 在DMA寄存器上配置通道优先级。
5. 根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。
6. 在DMA寄存器上激活该通道。
7. 当DMA控制器中指定的数据量传输完成时,DMA控制器在该DMA通道的中断向量上产生一中断。在中断服务程序里,软件应将USART_CR3寄存器的DMA位清零。 注意:如果DMA被用于发送,不要使能TXEIE位。
[编辑] 利用DMA接收
使用DMA进行接收,可以通过设置USART_CR3寄存器的DMAR位激活。只要接收到一个字节,数据就从USART_DR寄存器放到配置成使用DMA的SRAM区(参考DMA技术说明)。为USART的接收分配一个DMA通道步骤如下(x表示通道号):
1. 通过DMA控制寄存器把USART_DR寄存器地址配置成传输的源地址。在每个RXNE事件后此地址上的数据将传输到存储器。
2. 通过DMA控制寄存器把存储器地址配置成传输的目的地址。在每个RXNE事件后,数据将从USART_DR传输到此存储器区。
3. 在DMA控制寄存器中配置要传输的总的字节数。
4. 在DMA寄存器上配置通道优先级。
5. 根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。
6. 在DMA控制寄存器上激活该通道。
7. 当DMA控制器中指定的传输数据量接收完成时,DMA控制器在该DMA通道的中断矢量上产生一中断。在中断程序里, USART_CR3寄存器的DMAR位应该被软件清零。 注意: 如果DMA被用来接收,不要使能RXNEIE位。
[编辑] 多缓冲器通信中的错误标志和中断产生
在多缓冲器通信的情况下,通信期间如果发生任何错误,在当前字节传输后将置起错误标志。
如果中断使能位被设置,将产生中断。在单个字节接收的情况下,和RXNE一起被置起的帧错误、溢出错误和噪音标志,有单独的错误标志中断使能位;如果设置了,会在当前字节传输结束后,产生中断。
[编辑] 硬件流控制
利用nCTS输入和nRTS输出可以控制2个设备间的串行数据流。图253表明在这个模式里如何连接2个设备。
通过将UASRT_CR3中的RTSE和CTSE置位,可以分别独立地使能RTS和CTS流控制。
[编辑] RTS流控制
如果RTS流控制被使能(RTSE=1),只要USART接收器准备好接收新的数据,nRTS就变成有效(接低电平)。当接收寄存器内有数据到达时,nRTS被释放,由此表明希望在当前帧结束时停止数据传输。图254是一个启用RTS流控制的通信的例子。
[编辑] CTS流控制
如果CTS流控制被使能(CTSE=1),发送器在发送下一帧前检查nCTS输入。如果nCTS有效(被拉成低电平),则下一个数据被发送(假设那
个数据是准备发送的,也就是TXE=0),否则下一帧数据不被发出去。若nCTS在传输期间被变成无效,当前的传输完成后停止发送。
当CTSE=1时,只要nCTS输入一变换状态,CTSIF状态位就自动被硬件设置。它表明接收器是否准备好进行通信。如果USART_CT3寄存器的
CTSIE位被设置,中断产生。下图是一个CTS流控制被启用的通信的例子。
[编辑] USART中断请求
USART的各种中断事件被连接到同一个中断向量(见图256),有以下各种中断事件:
● 发送期间:发送完成中断、清除发送中断、发送数据寄存器空中断。
● 接收期间:空闲总线检测中断、溢出错误中断、接收数据寄存器非空中断、校验错误中断、LIN断开符号检测中断、噪音中断(仅在多缓冲器通信)和帧错误中断(仅在多缓冲器通信)。
如果对应的使能控制位被设置,这些事件就会产生各自的中断。

USART篇(二):关于USART接收中断的BUG和注意事项


问题描述:在使用USART做串口通讯时,我只把接收中断打开,并设置抢占优先级为最低一个级别,而接收中断上一个优先级处理事情比较多,可能占用了2ms时间。当我使用9600波特率往下位机发送数据,速度非常快,就是一直按回车发!问题就出来,不到1分钟时间,通讯没有反应了。USART配置代码如下:void
uart_config(void){USART_InitTypeDef
USART_InitStructure;USART_InitStructure.USART_BaudRate =
UART_GetBaud(BaudRate);USART_InitStructure.USART_WordLength =
USART_WordLength_8b;USART_InitStructure.USART_StopBits =
USART_StopBits_1;USART_InitStructure.USART_Parity =
USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode =
USART_Mode_Rx | USART_Mode_Tx;USART_InitStructure.USART_Clock =
USART_Clock_Disable;USART_InitStructure.USART_CPOL =
USART_CPOL_Low;USART_InitStructure.USART_CPHA =
USART_CPHA_2Edge;USART_InitStructure.USART_LastBit =
USART_LastBit_Enable;/* Configure USART1 */USART_Init(USART1,
&USART_InitStructure);/* Enable USART1 receive interrupt
*/USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);/* Enable the USART1
*/USART_Cmd(USART1, ENABLE);}分析问题:1.为什么没有通讯了?通过仿真器仿真,发现程序一直进入接收中断中,由于我没有使用中断发送,于是程序就死在了接收中断,也就没有数据发送到电脑上来。接收中断代码如下:void
UART_Receive(void){//正在处理上一条通讯,接收到数据不处理if(bRecieveOK){if(USART_GetITStatus(USART1,
USART_IT_RXNE) != RESET)USART_ClearITPendingBit(USART1,
USART_IT_RXNE);return;//processing receive data,don"t receive
again}if(USART_GetITStatus(USART1, USART_IT_RXNE) !=
RESET){if(MoudBusExpir == 0){ucRcePtr = 0;MoudBusExpir =
20;//50ms}elseMoudBusExpir = 20;/* Read one byte from the
receive data register */ucRS485Buff[ucRcePtr++] =
USART_ReceiveData(USART1);/* Clear the USART1 Receive interrupt
*/USART_ClearITPendingBit(USART1,
USART_IT_RXNE);}}2.为什么会一直跑到接收中断?断点之后发现(USART_GetITStatus(USART1,
USART_IT_RXNE)==RESET的,也就是说没有数据接收到也进了中断,而且在USART配置中我也只打开了接收中断!没有数据送过来应该是不可能进入中断的!3.响应了什么中断?我想通过函数(USART_GetITStatus()把所有中断状态都读出来,但失败了,USART_IT_XXX所有中断状态都是RESET!也就是说没有中断也进入到这个中断服务程序来了!?4.找资料STM32F10x微控制器参考手册(2009年12月第10版)P541发现如下说明:
下载 (123 KB)2010-3-12
16:38
也就是说只要接收中断打开,即RXNEIE设置为1,那么ORE中断也自动打开了。可是USART_GetITStatus(USART1,
USART_IT_ORE )== RESET!!!!找到USART_GetITStatus(USART1,
USART_IT_RXNE)函数,发现只有当USART_IT_ERR中断使能时,才能读到ORE中断。在这里要指出这个BUG:产生ORE中断了,但使用USART_GetITStatus()函数却无法读到这个中断被SET起来!5.把ORE中断标志位清除既然找到了是什么中断,那么把相应的中断标志位清除,就应该可以了吧?USART_ClearITPendingBit(USART1,
USART_IT_ORE);但是,结果是没有任何效果!清除之后,马上读ORE中断状态,USART_GetITStatus(USART1,
USART_IT_ORE)==RESET.程序仍然跑死在接收中断。再使用另一个函数USART_GetFlagStatus(USART1,
USART_FLAG_ORE) =
SET,原来ORE标志位还没有清除。6.问题解决为什么清除不掉?头疼了,再找找资料,有发现,在P523页如下图:接收中断程序改为:void UART_Receive(void){if (USART_GetFlagStatus(USART1,
USART_FLAG_ORE) != RESET)//注意!不能使用if(USART_GetITStatus(USART1, USART_IT_RXNE) !=
RESET)来判断{USART_ReceiveData(USART1);}//正在处理上一条通讯,接收到数据不处理if(bRecieveOK){if(USART_GetITStatus(USART1,
USART_IT_RXNE) != RESET)USART_ClearITPendingBit(USART1,
USART_IT_RXNE);return;//processing receive data,don"t receive
again}if(USART_GetITStatus(USART1, USART_IT_RXNE) !=
RESET){if(MoudBusExpir == 0){ucRcePtr = 0;MoudBusExpir =
20;//50ms}elseMoudBusExpir = 20;/* Read one byte from the
receive data register */ucRS485Buff[ucRcePtr++] =
USART_ReceiveData(USART1);/* Clear the USART1 Receive interrupt
*/USART_ClearITPendingBit(USART1,
USART_IT_RXNE);}}总结:注意问题:1.USART_ITConfig(USART1,
USART_IT_RXNE,
ENABLE);使能了接收中断,那么ORE中断也同时被开启了。2.ORE中断只能使用USART_GetFlagStatus(USART1,
USART_FLAG_ORE)
读到(没有使能USART_IT_ERR中断时)BUG建议:1.在STM32库中,能不能修改USART_GetITStatus()函数对USART_IT_ORE中断的处理?也就是我只要打开了接收中断,那么有ORE中断时,我也能使用USART_GetITStatus(USART1,USART_IT_ORE)读到.其它:在找资料的同时,发现STM32F10x微控制器参考手册(2009年12月第10版)中文翻译P538有错误,如下图:英文P696如下图:

USART篇(三):STM32的USART


STM32的USART STM32资料 b) 初始化函数定义:void USART_Configuration(void);        //定义串口初始化函数c) 初始化函数调用:void UART_Configuration(void); //串口初始化函数调用初始化代码:void USART_Configuration(void)                      //串口初始化函数{//串口参数初始化    USART_InitTypeDef USART_InitStructure;              //串口设置恢复默认参数
//初始化参数设置   USART_InitStructure.USART_BaudRate = 9600;                                  //波特率9600USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8位   USART_InitStructure.USART_StopBits = USART_StopBits_1;                 //1位停止字节   USART_InitStructure.USART_Parity = USART_Parity_No;                   //无奇偶校验   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打开Rx接收和Tx发送功能
USART_Init(USART1, &USART_InitStructure);                                         //初始化   USART_Cmd(USART1, ENABLE);                                                       //启动串口}
RCC中打开相应串口RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);
GPIO里面设定相应串口管脚模式//串口1的管脚初始化    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                      //管脚9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出   GPIO_Init(GPIOA, &GPIO_InitStructure);                            //TX初始化
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                    //管脚10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入   GPIO_Init(GPIOA, &GPIO_InitStructure);                             //RX初始化
d) 简单应用:发送一位字符USART_SendData(USART1, 数据); //发送一位数据while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待发送完毕接收一位字符while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){} //等待接收完毕变量= (USART_ReceiveData(USART1)); //接受一个字节
发送一个字符串先定义字符串:char rx_data[250];   然后在需要发送的地方添加如下代码   int i;                                                                   //定义循环变量while(rx_data!="\0")                                        //循环逐字输出,到结束字"\0"{USART_SendData(USART1, rx_data);          //发送字符    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待字符发送完毕    i++;}
e) USART注意事项:发动和接受都需要配合标志等待。只能对一个字节操作,对字符串等大量数据操作需要写函数
使用串口所需设置:RCC初始化里面打开RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx);GPIO里面管脚设定:串口RX(50Hz,IN_FLOATING);串口TX(50Hz,AF_PP);
f) printf函数重定义(不必理解,调试通过以备后用)(1) 需要c标准函数:#include "stdio.h"(2) 粘贴函数定义代码#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)   //定义为putchar应用(3) RCC中打开相应串口(4) GPIO里面设定相应串口管脚模式(6) 增加为putchar函数。int putchar(int c)                                           //putchar函数{   if (c == "\n"){putchar("\r");}                                //将printf的\n变成\r   USART_SendData(USART1, c);                                  //发送字符   while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待发送结束   return c;                                                     //返回值}
(8) 通过,试验成功。printf使用变量输出:%c字符,%d整数,%f浮点数,%s字符串,/n或/r为换行。注意:只能用于main.c中。
3、 NVIC串口中断的应用a) 目的:利用前面调通的硬件基础,和几个函数的代码,进行串口的中断输入练习。因为在实际应用中,不使用中断进行的输入是效率非常低的,这种用法很少见,大部分串口的输入都离不开中断。b) 初始化函数定义及函数调用:不用添加和调用初始化函数,在指定调试地址的时候已经调用过,在那个NVIC_Configuration里面添加相应开中断代码就行了。c) 过程:i. 在串口初始化中USART_Cmd之前加入中断设置:USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//TXE发送中断,TC传输完成中断,RXNE接收中断,PE奇偶错误中断,可以是多个。ii. RCC、GPIO里面打开串口相应的基本时钟、管脚设置iii. NVIC里面加入串口中断打开代码:NVIC_InitTypeDef NVIC_InitStructure;//中断默认参数
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道设置为串口1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //中断占先等级0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中断响应优先级0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //打开中断NVIC_Init(&NVIC_InitStructure);                                              //初始化
iv. 在stm32f10x_it.c文件中找到void USART1_IRQHandler函数,在其中添入执行代码。一般最少三个步骤:先使用if语句判断是发生那个中断,然后清除中断标志位,最后给字符串赋值,或做其他事情。void USART1_IRQHandler(void)                            //串口1中断{char RX_dat;                                                       //定义字符变量
   if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)   //判断发生接收中断   {USART_ClearITPendingBit(USART1,   USART_IT_RXNE);       //清除中断标志
GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)0x01);          //开始传输RX_dat=USART_ReceiveData(USART1) & 0x7F;                       //接收数据,整理除去前两位USART_SendData(USART1, RX_dat);                                     //发送数据while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}//等待发送结束   }}
d) 中断注意事项:可以随时在程序中使用USART_ITConfig(USART1, USART_IT_TXE, DISABLE);来关闭中断响应。NVIC_InitTypeDef NVIC_InitStructure定义一定要加在NVIC初始化模块的第一句。全局变量与函数的定义:在任意.c文件中定义的变量或函数,在其它.c文件中使用extern+定义代码再次定义就可以直接调用了。评论int i;                                                                   //定义循环变量while(rx_data!="\0")                                        //循环逐字输出,到结束字"\0"{USART_SendData(USART1, rx_data);          //发送字符    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待字符发送完毕    i++;} ///你这段代码中,i++没有任何作用
9-29 10:14int putchar(int c)                                           //putchar函数{   if (c == "\n"){putchar("\r");}                                //将printf的\n变成\r   USART_SendData(USART1, c);                                  //发送字符
////这段代码中,USART_SendData(USART1, c); ,c是错误的,在函数库中的正确格式为:USART_SendData(字符,指针)即:USART_SendData(CHAR,*C);

USART

https://m.shanpow.com/dl/433830/

推荐访问:usart接口
《USART.doc》
将本文的Word文档下载,方便收藏和打印
推荐:
下载文档
上一篇: bootstrap方法
下一篇: 管道接头标准
相关阅读通用挽联 
热点推荐