stm32采用队列方式接收和发送RS485串口数据/* 用于存储接收字节的缓冲区 - 大小必须是2的幂 /
static uint8_t Receive_Buffer_Data[512];
static FIFO_BUFFER Receive_Buffer;
/ 线上的静默时间 /
static struct mstimer Silence_Timer;
/ 波特率 */
static uint32_t Baud_Rate = 38400;
/* 在接收到的帧的最后一个八位的停止位结束后,节点可以启用其EIA-485驱动器之前的最短时间:40个位时间。/
/ 在9600波特率下,40个位时间约为4.166毫秒 /
/ 在19200波特率下,40个位时间约为2.083毫秒 /
/ 在38400波特率下,40个位时间约为1.041毫秒 /
/ 在57600波特率下,40个位时间约为0.694毫秒 /
/ 在76800波特率下,40个位时间约为0.520毫秒 /
/ 在115200波特率下,40个位时间约为0.347毫秒 /
/ 40位是包括每个八位的起始位和停止位的4个八位 */
#define Tturnaround (40UL)
/*************************************************************************
Description: 重置线上的静默时间计时器。
Returns: 无
Notes: 无
**************************************************************************/
void rs485_silence_reset(void)
{
mstimer_set(&Silence_Timer, 0);
}
/*************************************************************************
Description: 从计时器确定线上的静默时间。
Returns: 如果已经过了指定的时间间隔,则返回true
Notes: 无
**************************************************************************/
bool rs485_silence_elapsed(uint32_t interval)
{
return (mstimer_elapsed(&Silence_Timer) > interval);
}
/*************************************************************************
Description: 波特率决定了回转时间。
Returns: 毫秒数
Notes: 无
*************************************************************************/
static uint16_t rs485_turnaround_time(void)
{
/ 接收后传输之前的延迟 - 根据MS/TP规范 /
/ 等待至少40个位时间自接收以来 /
/ 至少2毫秒用于错误:四舍五入、时钟滴答 */
if (Baud_Rate) {
return (2 + ((Tturnaround * 1000UL) / Baud_Rate));
} else {
return 2;
}
}
/*************************************************************************
Description: 使用静默计时器确定回转时间。
Returns: 如果回转时间已过,则返回true。
Notes: 无
**************************************************************************/
bool rs485_turnaround_elapsed(void)
{
return (mstimer_elapsed(&Silence_Timer) > rs485_turnaround_time());
}
/*************************************************************************
Description: 确定接收时是否发生错误。
Returns: 如果发生错误,则返回true。
Notes: 无
**************************************************************************/
bool rs485_receive_error(void)
{
return false;
}
/*******************************************************************/
/
@brief
*USARTx
*中断
*处理程序
*子例程
@param[in]
*无
@return
*无
**********************************************************************/
void USART2_IRQHandler(void)
{
uint8_t data_byte;
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
/* 从接收数据寄存器中读取一个字节 */
data_byte = USART_ReceiveData(USART2);
(void)FIFO_Put(&Receive_Buffer, data_byte);
}
}
/*************************************************************************
DESCRIPTION: 返回是否有可用的字节。
RETURN: 如果有可用的字节,则返回true,并将字节存储在参数中。
NOTES: 无
**************************************************************************/
bool rs485_byte_available(uint8_t data_register)
{
bool data_available = false; / 返回值 */
if (!FIFO_Empty(&Receive_Buffer)) {
if (data_register) {
*data_register = FIFO_Get(&Receive_Buffer);
}
rs485_silence_reset();
data_available = true;
led_rx_on_interval(10);
}
return data_available;
}
/*************************************************************************
DESCRIPTION: 发送一个字节的数据。
RETURN: 无
NOTES: 无
**************************************************************************/
void rs485_byte_send(uint8_t tx_byte)
{
led_tx_on_interval(10);
USART_SendData(USART2, tx_byte);
rs485_silence_reset();
}
/*************************************************************************
Description: 确定USART中是否有一个字节从寄存器中移出。
Returns: 如果USART寄存器为空,则返回true。
Notes: 无
**************************************************************************/
bool rs485_byte_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TXE);
}
/*************************************************************************
Description: 确定整个帧是否从USART FIFO中发送完毕。
Returns: 如果USART FIFO为空,则返回true。
Notes: 无
**************************************************************************/
bool rs485_frame_sent(void)
{
return USART_GetFlagStatus(USART2, USART_FLAG_TC);
}
|