乐于分享
好东西不私藏

STM32仿三菱PLC程序设计(源码+电路原理图)

STM32仿三菱PLC程序设计(源码+电路原理图)
    在工业自动化领域,三菱PLC以其稳定性和易用性占据重要地位。然而,对于开发者和爱好者而言,自主实现一套兼容三菱协议的PLC系统不仅能降低成本,还能深入理解工业控制的核心原理。本文将结合硬件电路原理图和提供的STM32源码,详细介绍如何实现一款仿三菱PLC系统。

一、系统架构与硬件设计

1.1 核心控制单元

本系统采用STM32F103系列微控制器作为核心,其丰富的外设资源和强大的处理能力完全满足PLC的控制需求。STM32F103具备多个UART接口、定时器、ADC/DAC模块,可轻松实现数字量输入输出、模拟量采集、通信等功能。

1.2 硬件电路设计

说明:由于电路原理图有4页,因此这里仅截图一部分,可关注本人公众号

后台私信我领取资料

根据提供的原理图,系统主要包含以下几个部分:

  • 电源模块
    提供稳定的5V和3.3V电源,确保系统可靠运行。
  • 输入输出接口
    8路隔离数字量输入和8路隔离达林顿管输出,满足工业现场的信号采集和控制需求。
  • 通信接口
    RS232编程接口和RS485通信接口,支持与上位机、触摸屏、变频器等设备的通信。
  • 模拟量采集
    两个电位器输入,可用于模拟量信号的采集和调节。

二、软件系统设计

2.1 系统初始化

系统初始化是PLC运行的基础,包括时钟配置、GPIO初始化、定时器初始化、通信接口初始化等。以下是系统初始化的核心代码:

int main(void)

{

  //配置系统时钟

  sys_config();

  //配置 NVIC 和 Vector Table

  NVIC_Configuration();

  //配置使用的GPIO口

  GPIO_Configuration();

  //改变指定管脚的映射 GPIO_Remap_SWJ_JTAGDisable JTAG-DP 失能 + SW-DP使能

  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);

  xxdelay();

  SysTick_Config();

  I2C_EE_Init();

  Analog_Configration();

  DMA_Configration();

  program = (unsigned char *)(0x0800C000);

  UART0_setup();

  UART1_setup();

  LED0_OFF;

  LED1_OFF;

  //主循环

  plc_main();

}

2.2 输入输出处理

PLC的核心功能是实现输入信号的采集和输出信号的控制。在本系统中,输入信号通过GPIO口读取,输出信号通过GPIO口控制。以下是输入输出处理的核心代码:

/*

*输入更新函数,将外部输入信号 转换为 内部数据

******************************************************************************/

void update_input(void)

{

  unsigned int temp;

  //第一部分为数字量输出

  temp = ~GPIOC_IDR;

  temp = temp & 0x00ff;

  memory[P_X + 0] = temp;

  //第二部分为模拟量输出(两个电位器设定)

  memory[P_D + 2030] = sys_analog[0];

  memory[P_D + 2031] = sys_analog[1];

}

/******************************************************************************

*输出更新函数,将内部数据转换为 外部输出信号

*******************************************************************************/

void update_output(void)

{

  unsigned int temp;

  temp = 0;

  temp = memory[P_Y + 0];

  temp = temp << 8;

  GPIOB_BRR = temp;

  GPIOB_BSRR =(~temp)&(0xff00);

}

2.3 通信协议实现

本系统支持RS232和RS485通信接口,可与上位机、触摸屏等设备进行通信。通信协议采用三菱PLC的专用协议,确保与三菱编程软件的兼容性。以下是通信处理的核心代码:

/******************************************************************************

*通讯处理程序,232编程通讯,受主程序调用

*******************************************************************************/

void communicate(void)

{

  uart0_dispose();

  uart1_dispose();

}

/*******************************************************************/

* 名称:uart1_dispose()

* 功能:串口uart1数据处理。  专用编程接口

* 入口参数:无

* 出口参数:无

*******************************************************************/

void uart1_dispose(void)

{

  unsigned char bitres;

  unsigned short address;

  unsigned short length;

  unsigned short counter;

  unsigned char  ta;

  //

  unsigned short tc;

  if((uart1_rxptr > 4) && (uart1_time > 10))

  {

    if((uart1_rxbuf[0] == 0x00) || (uart1_rxbuf[0] ==  program[0x1b]) ) //通讯地址判断机制——8位模式    #### 以后用数据表参数代替

    {

      crc3 = uart1_rxbuf[uart1_rxptr - 2];

      crc4 = uart1_rxbuf[uart1_rxptr - 1];

      uart_crc(uart1_rxbuf , (uart1_rxptr - 2));

      if((crc3 == crc1)&&(crc4 == crc2))

      {

        switch(uart1_rxbuf[1])

        {

          case(0x01):

            address = uart1_rxbuf[2];

            address = address << 8;

            address |= uart1_rxbuf[3];

            bitres = address & 0x0f;

            address = address >> 4;

            length = uart1_rxbuf[4];

            length = length << 8;

            length |= uart1_rxbuf[5];

            if(length == 0) length = 1;

            ta = 0;

            uart1_txbuf[0] = uart1_rxbuf[0];

            uart1_txbuf[1] = uart1_rxbuf[1];

            //uart1_txbuf[2] =

            counter = 3;

            uart1_txbuf[counter] = 0;

            while(length)

            {

              if(memory[address] & (1<<bitres))

              {

                uart1_txbuf[counter] |= (1<<ta);

              }

              else

              {

                uart1_txbuf[counter] &= ~(1<<ta);

              }

              bitres++;

              if(bitres == 16)

              {

                bitres = 0;

                address ++;

              }

              ta++;

              length--;

              if((ta == 8)&(length != 0))

              {

                ta = 0;

                counter ++;

                uart1_txbuf[counter] = 0;

              }

            }

            uart1_txbuf[2] = counter - 2;

            uart_crc(uart1_txbuf,(counter + 1));

            uart1_txbuf[counter+1] = crc1;

            uart1_txbuf[counter+2] = crc2;

            uart1_txall = counter+2;

            uart1_txptr = 0;

            COM1_OUT;

            USART2->DR = uart1_txbuf[0];

            break;

          //其他指令处理...

        }       

        uart1_rxptr = 0;    //清空uart1的缓冲计数 以及 定时

        uart1_time = 0;

      }

      else

      {

        uart1_rxptr = 0;    //清空uart1的缓冲计数 以及 定时

        uart1_time = 0;

      }

    }

    else

    {

      uart1_rxptr = 0;    //清空uart1的缓冲计数 以及 定时

      uart1_time = 0;

    }

  }

  if((uart1_rxptr <= 4) && (uart1_time > 15))

  {

    uart1_rxptr = 0;    //清空uart1的缓冲计数 以及 定时

    uart1_time = 0;

  }

}

2.4 逻辑控制实现

PLC的逻辑控制功能是通过执行用户程序实现的。本系统支持梯形图语言编程,用户可以使用三菱编程软件GX Developer或GX Works2进行编程、下载、调试和监视。以下是逻辑控制的核心代码:

/******************************************************************************

*PLC外循环主程序

*******************************************************************************/

void plc_main(void)

{

  clear_output();

  //运行控制初始化

  sys_status = 0;

  sys_run_flag = 0;

  //全局变量初始化

  sys_counter_10t = 0;

  sys_counter_100t = 0;

  sys_counter_1ms = 0;

  sys_counter_10ms = 0;

  sys_counter_100ms = 0;

  //逻辑部分初始化

  //系统级参数读取

  system_setup();

  //掉电保存输出的恢复

  nv_load();

  memory[0] = 0;

  memory[1] = 0;

  memory[2] = 0;

  memory[3] = 0;

  //初始输入输出数据

  //update_input();

  //update_output();

  logic_recover();

  sys_status = 0x10; //初始启动进入手动运行控制模式

  sys_run_flag = 0;

  //主无限循环程序

  while(1)

  {

    //非运行模式程序

    if((sys_status == 0x10)||(sys_status == 0x20))

    {

      if(sys_run_flag) //从运行转换为停止状态的第一个处理程序,用于恢复寄存器

      {

        logic_recover();

        //在非运行状态,需要清楚所有的输出

        clear_output();

        //---

        sys_run_flag = 0;

        LED0_OFF;

        LED1_OFF;

        sys_loc_err = 0;

      }

      //运行控制状态的转换,开关模式下转换到运行状态

      if( (sys_status == 0x10) && ((GPIOA_IDR & (1<<6)) == 0) )sys_status = 0x30;

    }

    //运行模式程序

    if((sys_status == 0x30)||(sys_status == 0x40))

    {

      if(sys_run_flag == 0) //进入运行的第一个循环,处理特殊寄存器

      {

        sys_run_flag = 1;

        LED0_ON;

        //运行第一周期的特殊寄存器操作

        memory[P_M + 125] |= (1<<2);

        memory[P_M + 125] &= ~(1<<3);

        //-----

      }

      else if(sys_run_flag == 1) //度过了第一个循环,转而进入正常运行循环

      {

        sys_run_flag = 0xff;

        //解除运行第一周期的特殊寄存器操作

        memory[P_M + 125] &= ~(1<<2);

        memory[P_M + 125] |= (1<<3);

        memory[P_M + 125] |= (1<<0);

        memory[P_M + 125] &= ~(1<<1);

        //-----

      }

      //输入更新

      update_input();

      //逻辑堆栈复位

      logic_reset();

      execute_time = 0;//服务后台程序计时变量

      //用户程序执行

      program_excute();

      memory[P_D + 2001] = execute_time; //将程序运行计时数据传送到用户数据区

 memory[P_D + 2002] = sys_loc_err; //将程序运行计时数据传送到用户数据区

      //输出更新

      update_output();

      //转换信号处理

      if( (sys_status == 0x30) && (GPIOA_IDR & (1<<6)) )sys_status = 0x10;

      if( sys_loc_err ) LED1_ON;

    }

    //通讯处理程序

    communicate();

    if((GPIOB_IDR & 0x01)==0)      nv_save();

  }

}

三、系统调试与测试

3.1 硬件调试

硬件调试主要包括电源测试、输入输出测试、通信测试等。通过万用表、示波器等工具,确保硬件电路的正确性和稳定性。

3.2 软件调试

软件调试主要包括系统初始化调试、输入输出调试、通信调试、逻辑控制调试等。通过调试工具和上位机软件,确保软件系统的正确性和稳定性。

3.3 系统测试

系统测试主要包括功能测试、性能测试、稳定性测试等。通过模拟工业现场的实际工况,测试系统的各项功能和性能指标。

四、总结

本文详细介绍了如何实现一款仿三菱PLC系统。通过对系统架构、硬件设计、软件系统设计、系统调试与测试等方面的介绍,读者可以深入理解PLC的核心原理和实现方法。同时,本文提供的代码和调试方法也可以作为开发者和爱好者实现自己的PLC系统的参考。

下一步:根据文章中的代码和原理,搭建硬件电路,进行实际测试和调试,进一步优化系统性能和稳定性。

五、资料

自提链接:https://pan.baidu.com/s/17BagEmnS_GCwXfwwgh_sqg 提取码: 7w2i

注:有需要代做毕业设计或代完成平时课时作业的可在淘宝店铺中代做您的设计,店铺名:敏哥单片机类设计

想要做兼职的亦可关注本人公众号后台私信联系我!