查看: 1198|回复: 0
打印 上一主题 下一主题

发个STM32的MODBUS主节点程序

[复制链接]
跳转到指定楼层
沙发
发表于 2015-6-10 09:40:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于课题的原因被强迫用了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();
        Inverter.Comm=LISTENING;
        //关定时器TIM5
        TIM_Cmd(TIM5, DISABLE);
        USART_ITConfig(InverterUart,USART_IT_RXNE,ENABLE);
        RS485Read();
        Delay(200,Inverter.Comm);//既定延时400ms,若Inverter.Comm的值变化则退出
        ResetInverterComm();

        Inverter.Comm=TIME_OUT;
        //接收缓冲中数据长度为0,则表示超时无应答
    if(Inverter.Length==0)
    {
        Inverter.Error=TIME_OUT;   //("变频器应答超时");
                return ;
    }
Inverter.Comm=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<l;i+=2)
        {
            tmp=Inverter.RecvBuf;
            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);
                Inverter.Comm=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);
        }
}
转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表