串口发送的字节数和接收的字节数不一致 | 已解决
开发板:开天斧三.1 2022/8/27mcu:stc8h8k64u
时钟:24Mhz
串口1,time0做超时定时器
上位机:V6.96V-plus
hex模式发送“1”;接收到2个字节,多字节发送同样是2N的字节长度
#include <STC8H.H>
#include "modbus_rtu.h"
void Timer0_Init(void); //1毫秒@24.000MHz
void Uart1_Init(void); //115200bps@24.000MHz
void IO_Init(void); // 初始化IO口
uint16_t uart1_timeout = 0; // 通讯超时计数器
#define uart1_timeout_max 5 //通讯超时
bit timeout_flag = 0; // 超时标志位
// 你只需要改这 2 个参数
#define RX_BUF_MAX_LEN 64 // 接收缓冲区最大长度
#define RX_TIMEOUT_MS 10 // 超时时间(单位:ms)
// 全局变量
unsigned char UART_RX_BUF;// 接收缓冲区
unsigned intUART_RX_LEN = 0; // 已接收长度
unsigned char UART_RX_FLAG = 0; // 帧接收完成标志 1=完成
unsigned intUART_RX_TIMEOUT = 0; // 超时计数器
void Delay1ms(void) //@24.000MHz
{
unsigned char data i, j;
_nop_();
i = 32;
j = 40;
do
{
while (--j);
} while (--i);
}
void main(void)
{
uint16_t i = 0;
IO_Init(); // 初始化IO口
Timer0_Init(); // 初始化定时器0
Uart1_Init(); // 初始化串口1
EA = 1;
// P2 = 0x00;
while (1)
{
if (UART_RX_FLAG == 1) //接收完成标志
{
UART_RX_FLAG = 0; // 清除接收完成标志
SBUF = UART_RX_LEN;
/** for (i = 0; i < UART_RX_LEN; i++)
{
//SBUF = UART_RX_BUF;
while (!TI);
}
*/ UART_RX_LEN = 0;
}
}
}
void Timer0_Isr(void) interrupt 1
{
TF0 = 0; // 清除TF0标志位
if(UART_RX_LEN > 0 && UART_RX_FLAG == 0) // 正在接收数据
{
UART_RX_TIMEOUT++;// 每ms +1
// 超时判断:超过设定时间 → 帧结束
if(UART_RX_TIMEOUT >= RX_TIMEOUT_MS)
{
UART_RX_FLAG = 1; // 标记一帧接收完成
UART_RX_TIMEOUT = 0; //清除超时标志位
}
}
}
void Uart1_Isr(void) interrupt 4
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
if(UART_RX_FLAG == 0)// 还没接收完成
{
UART_RX_BUF = SBUF; // 存数据
UART_RX_LEN++;
UART_RX_TIMEOUT = 0; // 收到数据,清空计时器
// 防止缓冲区溢出
if(UART_RX_LEN >= RX_BUF_MAX_LEN)
{
UART_RX_LEN = 0;
}
}
}
}
void Uart1_Init(void) //115200bps@24.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCC; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //使能定时器1中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
void IO_Init(void) // 初始化IO口
{
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
}
void Timer0_Init(void) //1毫秒@24.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
#include <STC8H.H>
#include "modbus_rtu.h"
void Timer0_Init(void); //1毫秒@24.000MHz
void Uart1_Init(void); //115200bps@24.000MHz
void IO_Init(void); // 初始化IO口
uint16_t uart1_timeout = 0; // 通讯超时计数器
#define uart1_timeout_max 5 //通讯超时
bit timeout_flag = 0; // 超时标志位
// 你只需要改这 2 个参数
#define RX_BUF_MAX_LEN 64 // 接收缓冲区最大长度
#define RX_TIMEOUT_MS 10 // 超时时间(单位:ms)
// 全局变量
unsigned char UART_RX_BUF;// 接收缓冲区
unsigned intUART_RX_LEN = 0; // 已接收长度
unsigned char UART_RX_FLAG = 0; // 帧接收完成标志 1=完成
unsigned intUART_RX_TIMEOUT = 0; // 超时计数器
void Delay1ms(void) //@24.000MHz
{
unsigned char data i, j;
_nop_();
i = 32;
j = 40;
do
{
while (--j);
} while (--i);
}
void main(void)
{
uint16_t i = 0;
IO_Init(); // 初始化IO口
Timer0_Init(); // 初始化定时器0
Uart1_Init(); // 初始化串口1
EA = 1;
// P2 = 0x00;
while (1)
{
if (UART_RX_FLAG == 1) //接收完成标志
{
UART_RX_FLAG = 0; // 清除接收完成标志
SBUF = UART_RX_LEN;
/** for (i = 0; i < UART_RX_LEN; i++)
{
//SBUF = UART_RX_BUF;
while (!TI);
}
*/ UART_RX_LEN = 0;
}
}
}
void Timer0_Isr(void) interrupt 1
{
TF0 = 0; // 清除TF0标志位
if(UART_RX_LEN > 0 && UART_RX_FLAG == 0) // 正在接收数据
{
UART_RX_TIMEOUT++;// 每ms +1
// 超时判断:超过设定时间 → 帧结束
if(UART_RX_TIMEOUT >= RX_TIMEOUT_MS)
{
UART_RX_FLAG = 1; // 标记一帧接收完成
UART_RX_TIMEOUT = 0; //清除超时标志位
}
}
}
void Uart1_Isr(void) interrupt 4
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
if(UART_RX_FLAG == 0)// 还没接收完成
{
UART_RX_BUF = SBUF; // 存数据
UART_RX_LEN++;
UART_RX_TIMEOUT = 0; // 收到数据,清空计时器
// 防止缓冲区溢出
if(UART_RX_LEN >= RX_BUF_MAX_LEN)
{
UART_RX_LEN = 0;
}
}
}
}
void Uart1_Init(void) //115200bps@24.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCC; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //使能定时器1中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
void IO_Init(void) // 初始化IO口
{
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
}
void Timer0_Init(void) //1毫秒@24.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
“UART_RX_LEN++”有重复,建议去掉其中一个。
建议将接收数据时读取SBUF操作放在“RI = 0;”之后“if(UART_RX_FLAG == 0) ”之前,如果不读可能会重复引发中断。
ok啊,搞定了,没注意那条代码
页:
[1]