这里的描述不太好懂,我们一会结合程序设计就很好理解:
串口通信的超时中断
什么时候需要串口空闲中断呢?
没有固定帧尾的时候,虽然数据可能是定长的,但是如果数据是错误的呢?
在modbus rtui协议中,假设帧1是主机发送的,帧2是从机的回复命令,按照标准的modbus rtu协议来说,‘中间应该要间隔3.5个字符周期
有校验位:假设 1个字符=1(起始位)+8.(数据位)+1(奇偶校验位)+1(停止位)=11位3.5个字符=3.5*11=38.5位 如果波特率=9600bps,则3.5个字符间隔时间为38.5/9.6=4.0104167毫秒
无校验位:假设 1个字符=1(起始位)+8(数据位)+0(无校验位)+1(停止位)=10位
3.5个字符=3.5*10=35位
9600波特率下,8N1的空闲时间就是1/9600*35=3646ms:带入公式3646= 1/22.1184*计时器数值,得出计时器数值=87504=0x13b也就是无校验位的情况下约等于3.646毫秒
3个寄存器的值就出来了:
先改初始化:
void Uart2_Init(void) //9600bps@24.000MHz
{
P_SW2 |= 0x01; //UART2/USART2: RxD2(P4.6), TxD2
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x8F; //设置定时初始值
T2H = 0xFD; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x01; //使能串口2中断
UR2TOCR = 0x00; //关闭超时中断
UR2TOTL = 0x04; //比特率9600bps下8N1的
UR2TOTH = 0x3b; //空闲时间是OX13b04
UR2TOTE = 0x01;
/*9600波特率下,8N1的空闲时间就是 1/9600*35 ~3.646ms;
带入公式3646= 1/22.1184*计时器数值,得出计时器
数值=87504= 0x13b04;
*/
Rec_Num = 0;
B_TX2_Busy = 0;
B_RX2_OK = 0;
}
仔细看串口中断服务函数:
void Uart2_Isr(void) interrupt 8
{
if (S2CON & 0x02) //检测串口2发送中断
{
S2CON &= ~0x02; //清除串口2发送中断请求位
B_TX2_Busy = 0;
}
if (S2CON & 0x01) //检测串口2接收中断
{
S2CON &= ~0x01; //清除串口2接收中断请求位
UR2TOCR = 0xe0;//开启超时中断,使用系统时钟
//S2BUF
Rec_Dat = S2BUF;
}
if(UR2TOSR & 0x01) //串口超时中断
{
B_RX2_OK = 1; //接收完成标志位
UR2TOSR = 0x00; //清除超时标志位
UR2TOCR = 0x00; //关闭超时中断
}
}
接着可以处理接收到的数据:
void Usart2_RunTask(void)
{
if( B_RX2_OK == 1 )
{
B_RX2_OK = 0;
Uart2_SendStr( "接收成功!\r\n" );
}
// if( Rec_Num >= 6 ) //是否接收到了6位以上的数据
// {
// if(( Rec_Dat == '\n' ) && ( Rec_Dat == '\r' ) ) //末尾判断
// {
// if( ( Rec_Dat == 'O' ) && ( Rec_Dat == 'P' ) && ( Rec_Dat == 'E' ) && ( Rec_Dat == 'N' ))
// {
// passward = 16;
// passward = 16;
// passward = 16;
// passward = 16;
// Uart2_SendStr( "打开成功!\r\n" );
// }
// else if( ( Rec_Dat == 'C' ) && ( Rec_Dat == 'L' ) && ( Rec_Dat == 'O' ) && ( Rec_Dat == 'S' ) && ( Rec_Dat == 'E' ))
// {
// passward = 17;
// passward = 17;
// passward = 17;
// passward = 17;
// Uart2_SendStr( "关闭成功!\r\n" );
// }
// Rec_Num = 0;
// }
// }
}
编译下载后,在串口助手发字符串给单片机:
成功接收到单片机回复的信息:
最后看看课后小练:
那么第十八课到此结束
接着本来是要学习ADC的,但是按键之类的IO口好像都忘了
我们先复习一下IOI/0输入输出
GPIO(General Purpose I/O'Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们
读入引脚的状态-是高电平或是低电平。
参数: