STM32西门子PLC源码 双串口224XP源码 CPU:STM32F103RCT6/VCT6 针对型号:CPU224XP/CPU226(可通过宏定义切换,不需要单独分别购买,相当于买一送一)。 串口收发数据用DMA方式,通讯流畅稳定 两路RS232串口,支持同时连接编程软件和触摸屏,方便调试。
最近在工控圈子里折腾STM32复刻西门子PLC的项目有点火,今天咱们来扒一扒这个支持双串口的224XP方案。这玩意儿用STM32F103RCT6当大脑,最狠的是用宏定义就能在224XP和226型号之间无缝切换,相当于花一份钱买两套方案,这波操作属实把性价比玩明白了。
先看硬件配置,两路RS232串口才是这方案的精髓。传统PLC调试最蛋疼的就是接上触摸屏就没法连编程软件,这个双串口设计直接让开发效率翻倍。原理图上USART1和USART3分别挂着DMA通道,实测同时跑Modbus和PPI协议稳如老狗。
核心配置代码里藏着型号切换的魔法:
// 型号切换开关 #define IS_CPU224XP 1 // 1:224XP模式 0:226模式 #if IS_CPU224XP #define IO_GROUP_NUM 4 #define PWM_CHANNELS 2 #else #define IO_GROUP_NUM 6 #define PWM_CHANNELS 4 #endif这种预处理指令的玩法把硬件差异抽象得明明白白,编译时直接生成对应型号的固件。之前见过用跳线帽切换方案的,那真是弱爆了。
DMA配置是通讯流畅的关键,来看串口1的DMA初始化:
void USART1_DMA_Config(void) { DMA_InitTypeDef dma; DMA_DeInit(DMA1_Channel4); // USART1_TX dma.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; dma.DMA_MemoryBaseAddr = (uint32_t)uart1_tx_buffer; dma.DMA_DIR = DMA_DIR_PeripheralDST; // 内存到外设 dma.DMA_BufferSize = UART_BUF_SIZE; dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma.DMA_MemoryInc = DMA_MemoryInc_Enable; dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; dma.DMA_Mode = DMA_Mode_Normal; DMA_Init(DMA1_Channel4, &dma); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); }这配置直接把CPU从数据搬运中解放出来,特别是处理Modbus长帧时优势明显。实测9600波特率下连续发送512字节数据包,CPU占用率不到3%。
中断处理也有讲究,看这个USART3的接收中断:
void USART3_IRQHandler(void) { if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) { USART_ReceiveData(USART3); // 清中断 DMA_Cmd(DMA1_Channel2, DISABLE); uint16_t recv_len = USART3_RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel2); process_data(recv_len); // 协议解析 DMA_SetCurrDataCounter(DMA1_Channel2, USART3_RX_BUF_SIZE); DMA_Cmd(DMA1_Channel2, ENABLE); } }用IDLE中断判断帧结束比传统的超时检测靠谱得多,特别是在处理不定长数据时。配合DMA自动搬运,既能吃满带宽又能精准抓包。
实测时接昆仑通态触摸屏和STEP7-MicroWIN同时在线,监控变量时通讯毫无卡顿。这方案最骚的是在IO处理线程里还偷偷塞了个PID算法,拿来直接做温度控制也没压力。不过要吐槽的是源码里匈牙利命名法有点上头,变量名长得能当密码用,建议自己改的时候备个降压药。