TA的每日心情 | 开心 2019-4-2 16:02 |
---|
签到天数: 257 天 连续签到: 1 天 [LV.8]以坛为家I
|
本L最近驱动一个扫描头模块SE955,一直无法通讯成功,详细见:大家用过STM32F10X的uart流控功能吗?
https://www.cirmall.com/bbs/forum.php?mod=viewthread&tid=15126&fromuid=3087
特别让人不舒服的地方是这个模块需要UART的流控制功能,本L选择的是STM32F103RET6作为主控MCU,用流控制的uart2做通讯接口,搞腾了2-3周了,一直没进展。
也查了不少资料,以下是网文
“硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。
硬件流控制必须将相应的电缆线连上,用RTS/CTS(请求发送/清除发送)流控制时,应将通讯两端的RTS、CTS线对应相连,数据终端设备(如计算机)使用RTS来起始调制解调器或其它数据通讯设备的数据流,而数据通讯设备(如调制解调器)则用CTS来起动和暂停来自计算机的数据流。这种硬件握手方式的过程为:我们在编程时根据接收端缓冲区大小设置一个高位标志(可为缓冲区大小的75%)和一个低位标志(可为缓冲区大小的25%),当缓冲区内数据量达到高位时,我们在接收端将CTS线置低电平(送逻辑0),当发送端的程序检测到CTS为低后,就停止发送数据,直到接收端缓冲区的数据量低于低位而将CTS置高电平。RTS则用来标明接收设备有没有准备好接收数据。
常用的流控制还有还有DTR/DSR(数据终端就绪/数据设置就绪)。我们在此不再详述。由于流控制的多样性,我个人认为,当软件里用了流控制时,应做详细的说明,如何接线,如何应用。
”
翻看 STM32的用户手册
查到如下:
“
引脚 配置 GPIO配置
USARTx_RTS 硬件流量控制 推挽复用输出
USARTx_CTS 硬件流量控制 浮空输入或带上拉输入
”
根据此,我做了如下的配置:
使能CTS,RTS对应的外设功能,设置为输出。
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART2 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* USART2 GPIO config */
/* Configure USART2 Tx (PA.02) RTS (PA.01) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART2 Rx (PA.03) CTS (PA.00) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART2 mode config */
//USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_BaudRate = 9600;
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_RTS_CTS;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Cmd(USART2, ENABLE);
}
可是效果并没有出来,仍然无法进行通讯,我测量RTS脚,在发送数据其间一直是低电平。要接收数据 RTS发完数据必须拉高,实际情况下结果却没拉高。所以肯定通讯不了的。
可是对照《STM32的用户手册》中文翻译版有如下的说明:由于我在办公室的电脑上无法发图片,就不发图片了。具体在手册的537页
两个USART间的硬件流控制:通过将UASRT_CR3中的RTSE和CTSE置位,可以分别独立地使能RTS和CTS流控制。
RTS流控制
如果RTS流控制被使能(RTSE=1),只要USART接收器准备好接收新的数据,nRTS就变成有效(接低电平)。当接收寄存器内有数据到达时,nRTS被释放,由此表明希望在当前帧结束时停止数据传输。
CTS流控制
如果CTS流控制被使能(CTSE=1),发送器在发送下一帧前检查nCTS输入。如果nCTS有效(被拉成低电平),则下一个数据被发送(假设那个数据是准备发送的,也就是TXE=0),否则下一帧数据不被发出去。若nCTS在传输期间被变成无效,当前的传输完成后停止发送。
当CTSE=1时,只要nCTS输入一变换状态,硬件就自动设置CTSIF状态位。它表明接收器是否准备好进行通信。如果设置了USART_CT3寄存器的CTSIE位,则产生中断。
看描述貌似RTS,CTS信号是自动产生和检测的,
但是事实是根本不是这样。
本L有点恼火了,流控制不就是把RTS在发数据的时候拉低,接收数据的时候CTS设置为输入(浮空)状态吗?
我直接配制RTS,CTS所在I/O为输出输入口,采用象485控制一样的方式,发送前把RTS拉低,发送完数据把RTS拉高,CTS不预理睬,随便它去,反正uart的接收中断一直开着的,检测数据桢格式,可以完美接收数据的。
这样一修改,发送读取序列号的命令,神奇的一幕出现了,SE955有反应了,返回了序列号。
估计我还没吃透STM32F103的UART流控制功能,有经验的欢迎交流,我这里权当 抛砖引玉了!
得到一个结论:如果有设备需要UART流控制的功能,用一个标准UART+2根GPIO(用做CTS,RTS信号),就可以实现了。
|
|