发个STM32的MODBUS主节点程序
发个STM32的MODBUS主节点程序
由于课题的原因被强迫用了STM32(本来打算2440的),因此认识阿莫电子,看到了版上一众高手,并学了不少知识。在课题中很多芯片资料的细节都是来源于阿莫电子,快毕业了,潜水了太久,就分享一点STM32的程序,反正很多都是从坛子里学的,我只是整理下拿来用了,献丑了。
处理器STM32F103ZET6是买论坛上一摄像头大师的(感谢免费帮我修了次3232),软件用的KEIL3.5。
我的MODBUS是驱动变频器的,做主节点用,主要实现03功能号和06功能号。
#define RS485Read (GPIO_WriteBit(GPIOG, GPIO_Pin_13,Bit_RESET))
#define RS485Write (GPIO_WriteBit(GPIOG, GPIO_Pin_13,Bit_SET))
//MODBUS的06功能号,读多个寄存器
void ReadInverter(UINT16 Addr,UINT8 N,UINT16 *Values)
{
UINT8 i,l;
UINT16 tmp;
UINT16 *p;
//在发送缓冲里面填数据
Inverter.SendBuf[0]=InverterAddr;
Inverter.SendBuf[1]=ReadID;
Inverter.SendBuf[2]=Addr>>8;
Inverter.SendBuf[3]=Addr&0XFF;
Inverter.SendBuf[4]=0;
Inverter.SendBuf[5]=N;
//计算CRC16,填入发送缓冲尾
CalCRC(Inverter.SendBuf,6,Inverter.SendBuf+6);
//置RS485发送状态
RS485Write();
//发送数据缓冲
Uart_Send(InverterUart,Inverter.SendBuf,8);
//清发送缓冲
PurgeRecvBuf();
https://www.360docs.net/doc/2d8844523.html,m=LISTENING;
//关定时器TIM5
TIM_Cmd(TIM5, DISABLE);
USART_ITConfig(InverterUart,USART_IT_RXNE,ENABLE);
RS485Read();
Delay(200,https://www.360docs.net/doc/2d8844523.html,m);//既定延时400ms,若https://www.360docs.net/doc/2d8844523.html,m的值变化则退出ResetInverterComm();
https://www.360docs.net/doc/2d8844523.html,m=TIME_OUT;
//接收缓冲中数据长度为0,则表示超时无应答
if(Inverter.Length==0)
{
Inverter.Error=TIME_OUT; //("变频器应答超时");
return ;
}
https://www.360docs.net/doc/2d8844523.html,m=FINISHED;
//长度校验
if(Inverter.RecvBuf[2]!=Inverter.Length-5)
{
Inverter.Error=FrameErr;
return ;//("变频器数据长度错误");
}
CalCRC(Inverter.RecvBuf,Inverter.Length-2,CRC16);
//CRC校验
if(*(UINT16 *)(CRC16)!=*(UINT16 *)(Inverter.RecvBuf+Inverter.Length-2)) {
Inverter.Error=CheckErr;
return ;//("变频器校验错误");
}
else if(Inverter.RecvBuf[1]==ReadID+0X80)
{
//("变频器读错误,错误号在第三个字节");
switch(Inverter.RecvBuf[2])
{
case Invalid_Func:i =Invalid_Func; break;
case Invalid_Addr:i =Invalid_Addr; break;
case Invalid_Data:i =Invalid_Data; break;
case InverterErr :i =InverterErr ; break;
case InverterBusy:i =InverterBusy; break;
case CheckErr :i =CheckErr ; break;
default :i =UnknowErr ; break;
}
Inverter.Error=i;
return ;
}
//校验一切正常,变频器操作成功
else if(Inverter.RecvBuf[1]==ReadID)
{
l=Inverter.RecvBuf[2]+3;
p=(UINT16 *)Values;
//接收数据
for(i=3;i { tmp=Inverter.RecvBuf[i]; tmp=tmp<<8; tmp=tmp+Inverter.RecvBuf[i+1]; *p=tmp; p++; } Inverter.Error=MODBUS_OK;//("读入参数成功:"); return ; } //校验一切正常,变频器操作失败 else if(Inverter.RecvBuf[1]!=ReadID&&Inverter.RecvBuf[1]!=ReadID+0X80) { Inverter.Error=UnknowErr;//("变频器应答错误"); return ; } return ; } void TIM5_IRQHandler(void) { if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM5, TIM_IT_Update); TIM_ClearFlag(TIM5, TIM_IT_Update); https://www.360docs.net/doc/2d8844523.html,m=FINISHED; TIM_Cmd(TIM5, DISABLE); USART_ITConfig(InverterUart,USART_IT_RXNE,DISABLE); } } void USART3_IRQHandler(void) { if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART3, USART_IT_RXNE); if(Inverter.Length<=17) { Inverter.RecvBuf[Inverter.Length]=USART_ReceiveData(USART3); Inverter.Length++; } TIM_Cmd(TIM5, ENABLE); TIM_SetCounter(TIM5,0x0000); } }