单片机与威纶通触控屏通过RS485(1号线接B-,2号线接A+)通讯,协议采用modbus。
单片机做从机,威纶通触控屏做主机,只能主机访问从机,从机不能主动访问主机。站号对应着单片机的地址
Modbus 没有结束标志位,判断一帧数据是否传输完成取决于单片机是否在3.5个字符(大概4ms)的时间内收到数据,如果大于3.5个字符的时间内没有收到数据可以判定一帧数据接收完成。这个时候需要借助定时器,从没有接收到数据开始计时。
void TIM2_IRQHandler()
{
u8 st;
st= TIM_GetFlagStatus(TIM2, TIM_FLAG_Update);
if(st==SET)
{
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
if(modbus.timrun!=0)
{
modbus.timout++;
if(modbus.timout>=8)
{
modbus.timrun=0;
modbus.reflag=1;
}
}
}
}
这是定时器中断服务函数,这里设定的时大于8ms没有收到数据表示一帧数据接收完成,
void USART2_IRQHandler()
{
u8 st,sbuf;
st=USART_GetITStatus(USART2, USART_IT_RXNE);
if(st==SET)
{
sbuf=USART2->DR;
if( modbus.reflag==1)
{
return ;
}
modbus.rcbuf[modbus.recount++]=sbuf;
modbus.timout=0;
if(modbus.recount==1)
{
modbus.timrun=1;
}
}
}
void Mosbus_Event()
{
u16 crc;
u16 rccrc;
if(modbus.reflag==0)
{
return ;
}
crc= crc16(&modbus.rcbuf[0], modbus.recount-2);
rccrc=modbus.rcbuf[modbus.recount-2]*256 + modbus.rcbuf[modbus.recount-1];
if(crc == rccrc)
{
if(modbus.rcbuf[0] == modbus.myadd)
{
switch(modbus.rcbuf[1])
{
case 0: break;
case 1: break;
case 2: break;
case 3: Modbud_fun3(); break;
case 4: break;
case 5: break;
case 6: Modbud_fun6(); break;
case 7: break;
}
}
else if(modbus.rcbuf[0] == 0)
{
}
}
modbus.recount=0;
modbus.reflag=0;
}
代码下载别人的,第一次写博客,为了更好的理解,有什么问题欢迎讨论
|