/*
UCOS_II
STM32F10x_FWLib V3.5.0
*/
[1]includes.h
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "ucos_ii.h"
#include "os_cpu.h"
#include "os_cfg.h"
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "Seg_Moudle.h"
#include "USART2_Configuration.h"
#include "DMA1_CHANNEL_Configuration.h"
#include "ModbusSlave.h"
#include "key.h"
//#include "RunMachine.h"
#include "IIC.h"
#include "AT24C32.h"
#include "CRC16.h"
#endif
[2]USART2_Configuration.c
/* Includes ------------------------------------------------------------------*/
#ifndef __USART2_CONFIGURATION_H
#define __USART2_CONFIGURATION_H
#include "stdio.h"
#include "sys.h"
#define USART_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART2_RX 1 //使能(1)/禁止(0)串口1接收
extern u8 USART2_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 ,对外使用
//extern u8 USART2_DMA_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART2_RX_COUNT; //接收长度记录 ,对外使用
//如果想串口中断接收,请不要注释以下宏定义
void USART2_Configuration(u16 baud);
#endif
[3] USART2_Configuration.c
#include "includes.h"
void USART2_Configuration(u16 baud)
{
// 1、定义GPIO端口、串口USART、中断NVIC初始化结构体。
//定义初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_Structure;
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAW
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);//向量表存放在RAM中
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);//向量表存放在FLASH中
#endif
//2、打开相关外设时钟,GPIOA的时钟和引脚都在APB2总线上,USART2的时钟和引脚都在APB1总线上,所以可以直接操作,如下
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//3、给GPIO结构体成员赋值,设置引脚功能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PA.1 ModbusSlave发送接收选择
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //择 PA.2(TXD) 和 PA.3(RXD)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速度
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用Init函数初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //择 PA.2(TXD) 和 PA.3(RXD)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置模式为浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用Init函数初始化GPIO
//4、初始化GPIO端口之后我们就要配置中断分组和串口中断优先级,中断优先级分组只用设置一次。
//NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器。
//5、以上配置好之后我们就可以来配置USART了
USART_Cmd(USART2,DISABLE);
USART_Structure.USART_BaudRate = baud; //设置串口波特率
USART_Structure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //启用接收和传输模式
USART_Structure.USART_Parity = USART_Parity_No; //设置奇偶校验位
USART_Structure.USART_StopBits = USART_StopBits_1; //设置停止位
USART_Structure.USART_WordLength = USART_WordLength_8b; //设置发送或接收数据长度
USART_Structure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //指定是否启用硬件流控制模式
USART_Init(USART2, &USART_Structure); //调用Init函数初始化USART设置
#if EN_USART2_RX //如果使能了接收
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //使能串口接收中断标志位,当标志位为1时会触发中断
#endif
USART_Cmd(USART2,ENABLE); //使能串口1
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); //启动了DMA通道,它既可响应连到该通道上的外设的DMA请求
USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE); //启动了DMA通道,它既可响应连到该通道上的外设的DMA请求
USART_ClearFlag(USART2, USART_IT_IDLE); //清除标志位,防止误报
}
//6、最后我们不能忘记了编写口串口接收中断函数
//u8 USART2_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
u8 USART2_RX_COUNT; //接收状态标记
void USART2_IRQHandler(void) //串口中断函名字,固定写法
{
if(USART_GetFlagStatus(USART2, USART_FLAG_IDLE)!=RESET)
{
USART_ReceiveData(USART2);//清除IDLE flag
DMA_Cmd(DMA1_Channel6,DISABLE);
USART2_RX_COUNT=USART_REC_LEN-DMA_GetCurrDataCounter(DMA1_Channel6);
DMA1_CHANNEL6_USART2RX_Configuration();
}
}
[4] DMA1_CHANNEL_Configuration.h
#ifndef __DMA1_CHANNEL_CONFIGURATION_H
#define __DMA1_CHANNEL_CONFIGURATION_H
#include "stdio.h"
#include "sys.h"
#include "stm32f10x_dma.h"
#define DEBUG_USART2_DR_BASE (USART2_BASE + 0x04)
#define DEBUG_USART_DMA1_CLK RCC_AHBPeriph_DMA1
#define DEBUG_USART2_DMA1_CHANNEL6 DMA1_Channel6
#define DEBUG_USART2_DMA1_CHANNEL7 DMA1_Channel7
void DMA1_CHANNEL6_USART2RX_Configuration(void);
void DMA1_CHANNEL7_USART2TX_Configuration(u8 * buf,u16 len);
void MyDMA_Config(DMA_Channel_TypeDef* DMA_CHx,
u32 PeripheralAddr,
u32 MemoryAddr,
u32 TranDir,
u16 BufferSize);
#endif
[5] DMA1_CHANNEL_Configuration.c
#include "includes.h"
//u8 testA[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
//#define DEBUG_USART_DMA_STREAM DMA1_Stream7
/***************************************
*Function Name : DMA1_CHANNEL6_USART2RX_Configuration(void)
*Description : 配置DMA1的通道6为USART2RX
*INPUT1 : None
*INPUT2 : None
*RETURN : conResult
***************************************/
u8 USART2_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
void DMA1_CHANNEL6_USART2RX_Configuration()
{
DMA_InitTypeDef DMA_InitStructure;
/* 开启DMA时钟*/
RCC_AHBPeriphClockCmd(DEBUG_USART_DMA1_CLK,ENABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)DEBUG_USART2_DR_BASE;
//ModbusSlave_RX_BUF
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)USART2_RX_BUF;//
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;///接收传输DMA_DIR_PeripheralSRC,发送传输:DMA_DIR_PeripheralDST
DMA_InitStructure.DMA_BufferSize = USART_REC_LEN;//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA的外设递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//设置DMA的内存递增模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//设置DMA在访问时每次操作的数据长度
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
// DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问的
DMA_Init(DEBUG_USART2_DMA1_CHANNEL6,&DMA_InitStructure);//统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。
DMA_Cmd(DEBUG_USART2_DMA1_CHANNEL6,ENABLE);//使能通道
}
void DMA1_CHANNEL7_USART2TX_Configuration(u8 * buf,u16 TX_BUFFER_SIZE)
{
DMA_InitTypeDef DMA_InitStructure;
/* 开启DMA时钟*/
RCC_AHBPeriphClockCmd(DEBUG_USART_DMA1_CLK,ENABLE);
DMA_Cmd(DMA1_Channel7,DISABLE);//失能通道
DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)DEBUG_USART2_DR_BASE;
//ModbusSlave_RX_BUF
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)buf;//MAX64
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;///接收传输DMA_DIR_PeripheralSRC,发送传输:DMA_DIR_PeripheralDST
DMA_InitStructure.DMA_BufferSize = TX_BUFFER_SIZE;//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA的外设递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//设置DMA的内存递增模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//设置DMA在访问时每次操作的数据长度
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
// DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问的
DMA_Init(DEBUG_USART2_DMA1_CHANNEL7,&DMA_InitStructure);//统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。
DMA_Cmd(DEBUG_USART2_DMA1_CHANNEL7,ENABLE);//使能通道
DMA_ITConfig(DEBUG_USART2_DMA1_CHANNEL7, DMA_IT_TC, ENABLE); //使能串口接收中断标志位,当标志位为1时会触发中断
DMA_ClearFlag(DMA1_FLAG_TC7); //清除标志位,防止误报
}
void DMA1_Channel7_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC7)) //通道6传输完成中断
{
DMA_ClearITPendingBit(DMA1_IT_GL7); //清除DMA通道6中断全局标志位
DMA_Cmd(DMA1_Channel7,DISABLE);//失能通道
}
}
[6]CRC16.h
#ifndef __CRC16_H
#define __CRC16_H
#include "sys.h"
u16 crc16(u8 *puchMsg, u16 usDataLen);
#endif
[7]CRC16.C
u16 crc16(u8 *puchMsg, u16 usDataLen)
{
// 多项式 x16+x15+x2+1(0x8005) 0x8005按位颠倒后的结果为0xA001
u16 crc=0xffff;
u8 i,j;
if(usDataLen>78)return 0;
j=0;
while(j<usDataLen)
{
crc ^= puchMsg[j];
for(i=0;i<8;i++)
{//如果是1,则移位完了,再异或;如果是0,只移位
if(crc&0x01)//A1先比较最右边一位
{
//把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位,如果移出位为1,CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
crc>>=1;//A2再进行右移
crc ^= 0xA001;
}
else
{
crc>>=1;
}
}
j++;
}
i=crc%256;
j=crc/256;
crc=i*256+j;
return crc;
}
[8]ModbusSlave.h
#ifndef __ModbusSlave_H
#define __ModbusSlave_H
#include "includes.h"
#include "sys.h"
#define USART_TX_LEN 128 //定义最大接收字节数 128
#define holdDataRegLength 32 //定义最大寄存器长度
#define inputDataRegLength 32 //定义最大寄存器长度
#define IXLength 5 //定义最大寄存器长度
#define OXLength 5 //定义最大寄存器长度
#define ReadCoilState 0x01 //读线圈量
#define ReadInputDis 0x02 //读输入离散量
#define ReadHoldReg 0x03 //读保持寄存器
#define ReadInputReg 0x04 //读输入寄存器
#define ForceSingleCoil 0x05 //写位
#define WriteMultiCoils 0x0F //写多位
#define WriteSingleReg 0x06 //写单个寄存器
#define WriteMultiReg 0x10 //写多个寄存器
//modbus错误码
typedef enum Error_Code{
ErrCmd = 1, //非法功能码
ErrAddr = 2, //非法数据地址
ErrData = 3, //非法数据值
ErrBreakdown = 4, //从机设备故障
ErrBLength = 5, //数据过长
ErrOthers = 6, //其它错误
ErrCRC = 8, //校验错误
}Error_Code_485;
//接收数据结构体
typedef struct{
uint8_t nAddr;
uint8_t nCMD;
uint16_t nRegStartAddr;
uint16_t nRegLen;
uint16_t Recv_Data[(USART_REC_LEN-6)/2];
uint8_t Byte_Data[USART_REC_LEN-6];
}Stu485_Recv_t;
void ModbusSlave_TX_EN(u8 en);
void GetRegisterVal(u16 readStartPos,u16 *tempData);
void SetRegisterVal(u16 readStartPos,u16 *tempData);
void UsartClearRxBuffer(void);
void UsartClearTxBuffer(void);
void Read_CoilState(void);
void Read_InputDis(void);
void Read_HoldReg(void);
void Force_SingleCoil(void);
void Write_SingleReg(void);
void Write_MultiCoils(void);
void Write_MultiReg(void);
int Modbus_CRC_Check(u8 *buf,u8 len);
void Modbus_Send_Data(u8 *buf,u8 len);
void ModbusSlave(void);
u16 myPowTwo(u8 pow);
int LengthJudge(u8 nCMD,u16 startPos,u16 length,u16 typeofDataLength);
void Modbus_Send_Error(uint8_t Cmd, uint8_t Err);
#endif
[9]ModbusSlave.c
#include "includes.h"
u8 ModbusSlave_localAddr=1;//用于记录本站地址
u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
u8 ModbusSlave_TX_CNT=0;
u16 HoldDataReg[holdDataRegLength];
u16 InputDataReg[inputDataRegLength];
u16 OX[OXLength]; //代表是输出线圈,用功能码 0x01,0x05,0x0F 访问, 开头地址是 0 (这个后续说明)
u16 IX[IXLength]; //代表是输入线圈,用功能码 0x02 访问,开头地址是 1 (这个后续说明)
Stu485_Recv_t stu485Recv;
/*********************************
* Function Name : Modbus_Send_Data
* Description : //485发送数据
* Input1 : u8 *buf要发送的数据
* Input2 : u8 len,要发送的字节数量
* Output : None
* Return : None
*
**********************************/
void Modbus_Send_Data(u8 *buf,u8 len)
{
ModbusSlave_TX_EN(1);
DMA1_CHANNEL7_USART2TX_Configuration(buf,len);
USART2_RX_COUNT=0;
ModbusSlave_TX_EN(0);//设为接收模式
}
/*********************************
* Function Name : Modbus_CRC_Check
* Description : //查询485接收的数据CRC正确性
* Input1 : u8 *buf buf接收缓存首地址
* Input2 : u8 len 读到的数据长度
* Output : None
* Return : 校验正确返回1,否则返回0
*
**********************************/
int Modbus_CRC_Check(u8 *buf,u8 len)
{
u8 ifRc=0;
u16 crcCheck;
//CRC校验
crcCheck=crc16(buf,len-2);
if(crcCheck==((buf[len-2]<<8)+buf[len-1]))
{
ifRc=1;//标志
}
return ifRc;
}
/*********************************
* Function Name : ModbusSlave_TX_EN
* Description : //设置485为发送还是接收(允许发送的IO口接max485的RE/DE,如USART2,PA1)
* Input1 : u8 en,1为发送,0为接收
* Output : None
* Return : None
*
**********************************/
void ModbusSlave_TX_EN(u8 en)
{
if(en==1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
/*********************************
* Function Name : ModbusSlave
* Description : //判断站号是否相同,并根据相应的功能码选择处理函数
* Input1 :
* Input2 :
* Output : None
* Return : None
*
“01”读取线圈状态
“02”读取输入状态
“03”保持型寄存器读取
“04”输入寄存器读取
“05”写单一线圈
“06”写单一寄存器
“15(0x0F)”写多线圈
“16(0x10)”写多寄存器
4.支持的MODBUS功能码
功能码01H:读取开关量输出
功能码02H:读取开关量输入
功能码03H:读取保持寄存器
功能码04H:读取输入寄存器
功能码05H:强制单点继电器输出
功能码06H:向保持寄存器写单个字
功能码0FH:强制多个继电器输出
功能码10H: 向保持寄存器(内存区)写多个16位的字(通讯对时)。
**********************************/
void ModbusSlave(void)
{
if(USART2_RX_COUNT>=8) //485通讯最少字节数
{
if(USART2_RX_BUF[0]==ModbusSlave_localAddr)//本地址才响应
{
if(Modbus_CRC_Check(USART2_RX_BUF,USART2_RX_COUNT))//CRC校验
{
if(USART2_RX_BUF[1]==0x01||USART2_RX_BUF[1]==0x02||USART2_RX_BUF[1]==0x03||USART2_RX_BUF[1]==0x04||USART2_RX_BUF[1]==0x05||USART2_RX_BUF[1]==0x06||USART2_RX_BUF[1]==0x0F||USART2_RX_BUF[1]==0x10)//判断功能码
{
switch(USART2_RX_BUF[1])
{
case ReadCoilState: Read_CoilState();//0x01
break;
case ReadInputDis: Read_InputDis();//0x02
break;
case ReadHoldReg:
case ReadInputReg: Read_HoldReg();//0x03,0x04
break;
case ForceSingleCoil: Force_SingleCoil();//0x05
break;
case WriteSingleReg: Write_SingleReg();//0x06
break;
case WriteMultiCoils: Write_MultiCoils();//0x0f
break;
case WriteMultiReg: Write_MultiReg();//0x10
break;
}
}
else
{
Modbus_Send_Error(USART2_RX_BUF[1],ErrCRC);//功能码错误
}
}
else
{
//Modbus_Send_Error(uint8_t Cmd, uint8_t Err);
Modbus_Send_Error(USART2_RX_BUF[1],ErrCmd);//CRC校验错误
}
}
}
}
/*********************************
* Function Name : LengthJudge()
* Description : 判断操作的数据内容是否有超过数据总长
* Input1 : startPos 操作起始位置
* Input2 : length 操作的长度
* Input3 : regDataLength设备中规定的相应类型的数据的总长
* Output : 返回处理的结果
* Return : None
*
**********************************/
int LengthJudge(u8 nCmd,u16 startPos,u16 length,u16 typeofDataLength)
{
if(length>typeofDataLength)//如果读取数量超过holdDataRegLength报错
{
Modbus_Send_Error(nCmd,ErrAddr);//地址错误
return 0;
}
if(!((startPos+length)<(typeofDataLength+1)))//如果起始地址正确,且总长度小于内部寄存器长度(holdDataRegLength+1)
{
Modbus_Send_Error(nCmd,ErrAddr); //数据过长
return 0;
}
return 1;
}
/*********************************
* Function Name : GetRegisterVal
* Description : //根据位置返回一个16位数据给指针
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void GetRegisterVal(u16 readStartPos,u16 *tempData)
{
*tempData=HoldDataReg[readStartPos];
}
/*********************************
* Function Name : SetRegisterVal
* Description : //把相应位置的16位数据设置好
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void SetRegisterVal(u16 writeStartPos,u16 *tempData)
{
HoldDataReg[writeStartPos]=*tempData;
}
/*********************************
* Function Name : UsartClearBuffer
* Description : //清除缓存区数据
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void UsartClearRxBuffer(void)
{
u8 i;
//USART2_RX_BUF;
//ModbusSlave_oneTime_Len;
for(i=0;i<USART_REC_LEN;i++)
{
USART2_RX_BUF[i]=0xFF;
}
}
void UsartClearTxBuffer(void)
{
// u8 i;
// //USART2_RX_BUF;
// //ModbusSlave_oneTime_Len;
// for(i=0;i<USART_TX_LEN;i++)
// {
// ModbusSlave_Tx_Buf[i]=0xFF;
// }
}
/**************************************
//函数功能:Modbus错误码发送
//函数返回值:无
//函数形参:Cmd:命令码,Err:错误类型
//时间:2020/06/22
//备注:无
*************************************/
void Modbus_Send_Error(uint8_t Cmd, uint8_t Err)
{
uint16_t crcCheck = 0;
ModbusSlave_Tx_Buf[0] = ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1] = 0x80 + Cmd;
ModbusSlave_Tx_Buf[2] = Err;
crcCheck=crc16(ModbusSlave_Tx_Buf,3);
ModbusSlave_Tx_Buf[3]=crcCheck/256;
ModbusSlave_Tx_Buf[4]=crcCheck%256;
Modbus_Send_Data(ModbusSlave_Tx_Buf,5);
}
/**************************************
//函数功能:myPowTwo计算2的几次方
//函数返回值:无
//函数形参:Cmd:命令码,Err:错误类型
//时间:2020/06/22
//备注:无
*************************************/
u16 myPowTwo(u8 pow)
{
u16 tmpA=1;
tmpA = tmpA<<pow;
return tmpA;
}
[10]Read_HoldReg.c
#include "includes.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern Stu485_Recv_t stu485Recv;
extern u16 HoldDataReg[holdDataRegLength];
extern u16 InputDataReg[inputDataRegLength];
/*********************************
* Function Name : Read_HoldReg
* Description : //读取保持寄存器0x03
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void Read_HoldReg(void)
{
// u8 i,j;
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);;//0x06写单个16位寄存器
if(stu485Recv.nCMD==ReadHoldReg)
{
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,holdDataRegLength))
{
return;
}
}
if(stu485Recv.nCMD==ReadInputReg)
{
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,inputDataRegLength))
{
return;
}
}
// j=0;
if(stu485Recv.nCMD==ReadHoldReg||stu485Recv.nCMD==ReadInputReg)
{
u16 byteCount,crcData;
u16 tmpRsbuf[1];
u16 i,j;
ModbusSlave_TX_CNT=0;
byteCount=stu485Recv.nRegLen*2;
j=0;
for(i=0;i<stu485Recv.nRegLen;i++)
{
if(stu485Recv.nCMD==ReadHoldReg)
{
memcpy(&tmpRsbuf,&HoldDataReg[stu485Recv.nRegStartAddr+i],2);//16位
}
if(stu485Recv.nCMD==ReadInputReg)
{
memcpy(&tmpRsbuf,&InputDataReg[stu485Recv.nRegStartAddr+i],2);//16位
}
ModbusSlave_Tx_Buf[j+3]=tmpRsbuf[0]>>8;
ModbusSlave_Tx_Buf[j+4]=(u8)(tmpRsbuf[0]&0x00FF);
j+=2;
}
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=byteCount;
byteCount+=3;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
UsartClearRxBuffer();
//ModbusSlave_TX_CNT;
}
UsartClearRxBuffer();
}
[11] Write_SingleReg.c
#include "includes.h"
#include "ModbusSlave_A.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern Stu485_Recv_t stu485Recv;
extern u16 HoldDataReg[holdDataRegLength];
/*********************************
* Function Name : Write_SingleReg
* Description : 写单个寄存器0x06
* Input1 :
* Input2 :
* Output : None
* Return : None
*
主:01 06 00 00 ff fa 48 79
//把40001(ffff)
从:01 06 00 00 ff fa 48 79
**********************************/
void Write_SingleReg(void)
{
u16 i,j;
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=1;//0x06写单个16位寄存器
memcpy(stu485Recv.Recv_Data,&USART2_RX_BUF[4],stu485Recv.nRegLen*2);//memcpy一次一个u8,u16要2个u8
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,holdDataRegLength))
{
return;
}
j=0;
for(i=0;i<stu485Recv.nRegLen;i+=2)
{
stu485Recv.Recv_Data[j]=((USART2_RX_BUF[i+4]<<8)+USART2_RX_BUF[i+5]);
j++;
}
//实现具体写入功能
if(stu485Recv.nCMD==WriteSingleReg)
{
u8 byteCount=0;
u16 crcData;
memcpy(&HoldDataReg[stu485Recv.nRegStartAddr],&stu485Recv.Recv_Data,stu485Recv.nRegLen*2);
ModbusSlave_Tx_Buf[4]=USART2_RX_BUF[4];
ModbusSlave_Tx_Buf[5]=USART2_RX_BUF[5];
byteCount+=2;
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=(u8)(stu485Recv.nRegStartAddr>>8);
ModbusSlave_Tx_Buf[3]=(u8)(stu485Recv.nRegStartAddr&0x00FF);
byteCount+=4;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
}
UsartClearRxBuffer();
}
/*********************************
//原有的程序保留一下
void ReadHoldRegisters(void)
{
u16 readByteLength;
u16 readStartPos;
u8 readFunc;
//u16 crcCheck;
readByteLength=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);
readStartPos=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
readFunc=USART2_RX_BUF[1];
if(!LengthJudge(0x03,readStartPos,readByteLength,holdDataRegLength))
{
return;
}
if(readFunc==0x03)
{
u16 byteCount,tempData,crcData;
u8 i;
ModbusSlave_TX_CNT=0;
tempData=0;
byteCount=readByteLength*2;
for(i=0;i<byteCount;i+=2,readStartPos++)
{
GetRegisterVal(readStartPos,&tempData);
ModbusSlave_Tx_Buf[i+3] = tempData >> 8;
ModbusSlave_Tx_Buf[i+4] = tempData & 0xff;
}
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=readFunc;
ModbusSlave_Tx_Buf[2]=byteCount;
byteCount+=3;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
UsartClearRxBuffer();
//ModbusSlave_TX_CNT;
}
}
************************************/
[12] Write_MultiReg.c
#include "includes.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern Stu485_Recv_t stu485Recv;
extern u16 HoldDataReg[holdDataRegLength];
/*********************************
* Function Name : Write_MultiRegister
* Description : 写多个寄存器0x10
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void Write_MultiReg(void)
{
u16 i,j;
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);//0x06写单个16位寄存器
//memcpy(stu485Recv.Recv_Data,&USART2_RX_BUF[4],stu485Recv.nRegLen*2);
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,holdDataRegLength))
{
return;
}
j=0;
for(i=0;i<stu485Recv.nRegLen*2;i+=2)
{
stu485Recv.Recv_Data[j]=((USART2_RX_BUF[i+7]<<8)+USART2_RX_BUF[i+8]);
j++;
}
if(stu485Recv.nRegStartAddr>holdDataRegLength)//判断寄存器地址
{
Modbus_Send_Error(USART2_RX_BUF[1],ErrAddr);//地址错误
return;
}
//实现具体写入功能
if(stu485Recv.nCMD==WriteMultiReg)
{
u16 crcCheck;
memcpy(&HoldDataReg[stu485Recv.nRegStartAddr],&stu485Recv.Recv_Data,stu485Recv.nRegLen*2);
ModbusSlave_Tx_Buf[0]=stu485Recv.nAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=stu485Recv.nRegStartAddr/256;
ModbusSlave_Tx_Buf[3]=stu485Recv.nRegStartAddr%256;
ModbusSlave_Tx_Buf[4]=stu485Recv.nRegLen/256;
ModbusSlave_Tx_Buf[5]=stu485Recv.nRegLen%256;
crcCheck=crc16(ModbusSlave_Tx_Buf,6);
ModbusSlave_Tx_Buf[6]=crcCheck/256;
ModbusSlave_Tx_Buf[7]=crcCheck%256;
Modbus_Send_Data(ModbusSlave_Tx_Buf,8);
UsartClearRxBuffer();
}
}
[13] Read_CoilState.c 说到写线圈,不得不说自己指针没有学好,写得自己都不好意思贴出来
#include "includes.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern u16 OX[OXLength];
extern Stu485_Recv_t stu485Recv;
/*********************************
* Function Name : Read_CoilState
* Description : //读输出线圈//0x01
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void Read_CoilState(void)
{
u16 byteCount,crcData;
u16 i,j;
u8 XXArray[OXLength*16]; //这里就是我SB的地方了,不会啊,没办法,只有用这个替代了。
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);//0x06写单个16位寄存器
//判断数据是否超长
if(stu485Recv.nCMD==ReadCoilState)
{
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,OXLength*16))
{
return;
}
for(i=0;i<OXLength;i++)
{
for(j=0;j<16;j++)
{
XXArray[i*16+j]=((OX[i]&myPowTwo(j))>0)?1:0;
}
}
//开始处理数据
byteCount=stu485Recv.nRegLen/8;
for(i=0;i<byteCount;i++)
{
u16 tmpA=0;
for(j=0;j<8;j++)
{
tmpA +=(XXArray[stu485Recv.nRegStartAddr+i*8+j]<<j);
}
stu485Recv.Byte_Data[i]=tmpA;
}
if(stu485Recv.nRegLen%8!=0)//把余下的加进来
{
u8 tmpByte=0;
for(i=0;i<stu485Recv.nRegLen%8;i++)
{
tmpByte+=(XXArray[(stu485Recv.nRegStartAddr+8*byteCount)+i]<<i);
}
stu485Recv.Byte_Data[byteCount]=tmpByte;
byteCount++;
}
//组合数据发送
memcpy(&ModbusSlave_Tx_Buf[3],&stu485Recv.Byte_Data,byteCount*2);//byteCount=4位,所以,u8=byteCount*2
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=byteCount;
byteCount+=3;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
UsartClearRxBuffer();
}
}
[14]Read_InputDis.c //这是最开始SB的写法,虽然0x01和0x02执行过程是一样的,但是还是保留了下来
#include "includes.h"
#include "ModbusSlave_A.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern Stu485_Recv_t stu485Recv;
extern u16 IX[IXLength];
/*********************************
* Function Name : Read_InputDis
* Description : //输入开关量状态//x02
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void Read_InputDis(void)
{
u16 byteCount,crcData;
u16 i;
u8 XXArray[IXLength*16];
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);//0x06写单个16位寄存器
//判断数据是否超长
if(stu485Recv.nCMD==ReadInputDis)
{
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,IXLength*16))
{
return;
}
for(i=0;i<IXLength;i++)
{
//低八位
XXArray[i*16+0]=((IX[i]&0x0001)>0)?1:0;//10001
XXArray[i*16+1]=((IX[i]&0x0002)>0)?1:0;
XXArray[i*16+2]=((IX[i]&0x0004)>0)?1:0;
XXArray[i*16+3]=((IX[i]&0x0008)>0)?1:0;
XXArray[i*16+4]=((IX[i]&0x0010)>0)?1:0;
XXArray[i*16+5]=((IX[i]&0x0020)>0)?1:0;
XXArray[i*16+6]=((IX[i]&0x0040)>0)?1:0;//10007
XXArray[i*16+7]=((IX[i]&0x0080)>0)?1:0;//10008
//高八位
XXArray[i*16+8]=((IX[i]&0x0100)>0)?1:0;//10009
XXArray[i*16+9]=((IX[i]&0x0200)>0)?1:0;
XXArray[i*16+10]=((IX[i]&0x0400)>0)?1:0;
XXArray[i*16+11]=((IX[i]&0x0800)>0)?1:0;
XXArray[i*16+12]=((IX[i]&0x1000)>0)?1:0;
XXArray[i*16+13]=((IX[i]&0x2000)>0)?1:0;
XXArray[i*16+14]=((IX[i]&0x4000)>0)?1:0;
XXArray[i*16+15]=((IX[i]&0x8000)>0)?1:0;//10016
}
//开始处理数据
byteCount=stu485Recv.nRegLen/8;
for(i=0;i<byteCount;i++)
{
stu485Recv.Byte_Data[i]=
XXArray[stu485Recv.nRegStartAddr+i*8+0]+
(XXArray[stu485Recv.nRegStartAddr+i*8+1]<<1)+
(XXArray[stu485Recv.nRegStartAddr+i*8+2]<<2)+
(XXArray[stu485Recv.nRegStartAddr+i*8+3]<<3)+
(XXArray[stu485Recv.nRegStartAddr+i*8+4]<<4)+
(XXArray[stu485Recv.nRegStartAddr+i*8+5]<<5)+
(XXArray[stu485Recv.nRegStartAddr+i*8+6]<<6)+
(XXArray[stu485Recv.nRegStartAddr+i*8+7]<<7);
}
if(stu485Recv.nRegLen%8!=0)//把余下的加进来
{
u8 tmpByte=0;
for(i=0;i<stu485Recv.nRegLen%8;i++)
{
tmpByte+=(XXArray[(stu485Recv.nRegStartAddr+8*byteCount)+i]<<i);
}
stu485Recv.Byte_Data[byteCount]=tmpByte;
byteCount++;
}
//组合数据发送
memcpy(&ModbusSlave_Tx_Buf[3],&stu485Recv.Byte_Data,byteCount*2);//byteCount=4位,所以,u8=byteCount*2
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=byteCount;
byteCount+=3;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
}
UsartClearRxBuffer();
}
[15] Force_SingleCoil.c
#include "includes.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern u16 OX[OXLength];
extern Stu485_Recv_t stu485Recv;
/*********************************
* Function Name : Force_SingleCoil
* Description : //强制单个线圈//0x05
* Input1 :
* Input2 :
* Output : None
* Return : None
*
* 主:01 05 00 00 ff 000 8c 3a //把10001置1
* 从:01 05 00 00 ff 000 8c 3a
**********************************/
void Force_SingleCoil(void)
{
u16 coilBytePos;
u8 coilArrayPos;
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=1;
stu485Recv.Recv_Data[0]=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);
if(stu485Recv.nCMD==ForceSingleCoil)
{
//u16 crcCheck;
u8 byteCount=0;
u16 crcData;
//memcpy(&HoldDataReg[stu485Recv.nRegStartAddr],&stu485Recv.Recv_Data,stu485Recv.nRegLen*2);
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,OXLength*16))
{
return;
}
coilBytePos=stu485Recv.nRegStartAddr/16;
coilArrayPos=stu485Recv.nRegStartAddr%16;
if(stu485Recv.Recv_Data[0])
{
OX[coilBytePos]=OX[coilBytePos]|(1<<coilArrayPos);
}
else
{
OX[coilBytePos]=OX[coilBytePos]&(~(1<<coilArrayPos));
}
ModbusSlave_Tx_Buf[4]=USART2_RX_BUF[4];
ModbusSlave_Tx_Buf[5]=USART2_RX_BUF[5];
byteCount+=2;
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=(u8)(stu485Recv.nRegStartAddr>>8);
ModbusSlave_Tx_Buf[3]=(u8)(stu485Recv.nRegStartAddr&0x00FF);
byteCount+=4;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
}
UsartClearRxBuffer();
}
[16] Write_MultiCoils.c
#include "includes.h"
extern u8 ModbusSlave_localAddr;//用于记录本站地址
extern u8 ModbusSlave_TX_CNT;
extern u8 ModbusSlave_Tx_Buf[USART_TX_LEN];//
extern u16 OX[OXLength];
extern Stu485_Recv_t stu485Recv;
/*********************************
* Function Name : Write_MultiCoils
* Description : 写多个寄存器0x0f
* Input1 :
* Input2 :
* Output : None
* Return : None
*
**********************************/
void Write_MultiCoils(void)
{
u16 crcData;
u8 byteCount=0;
u16 i,j,k;
u8 XXArray[OXLength*16];
stu485Recv.nAddr=USART2_RX_BUF[0];
stu485Recv.nCMD=USART2_RX_BUF[1];
stu485Recv.nRegStartAddr=((USART2_RX_BUF[2]<<8)+USART2_RX_BUF[3]);
stu485Recv.nRegLen=((USART2_RX_BUF[4]<<8)+USART2_RX_BUF[5]);
memcpy(stu485Recv.Byte_Data,&USART2_RX_BUF[7],USART2_RX_BUF[6]);
if(stu485Recv.nCMD==WriteMultiCoils)
{
if(!LengthJudge(stu485Recv.nCMD,stu485Recv.nRegStartAddr,stu485Recv.nRegLen,OXLength*16))
{
return;
}
for(i=0;i<OXLength;i++)
{
/*
主:H 01 0f 00 01 00 17 03 80 80 40 65 6d 0x17=23
// 0x3f=高00111111低 0xbf=10111111
//把10001置0 把10002置0 10003置0 10004置0 10005置0 10006置0 10007置0 10008置1
//把10009置0 把10010置0 10011置0 10012置0 10013置0 10014置0 10015置0 10016置1
//把10017置0 把10018置0 10019置0 10020置0 10021置0 10022置0 10023置1
从:H 01 0f 00 01 00 17 44 05
*/
for(j=0;j<16;j++)
{
XXArray[i*16+j]=((OX[i]&myPowTwo(j))>0)?1:0;
}
}
//开始处理数据
//MoveMemToStart(u16 startPos, u16 nLength,u16 * MemorySourece, u16 * MemoryDest)
j=0;
for(i=0;i<stu485Recv.nRegLen/8;i++)
{
for(k=0;k<8;k++)
{
XXArray[stu485Recv.nRegStartAddr+j]=((stu485Recv.Byte_Data[i]&myPowTwo(k))>0)?1:0;
j++;
}
}
//补足8的余数
if(stu485Recv.nRegLen%8!=0)
{
for(i=0;i<stu485Recv.nRegLen%8;i++)
{
XXArray[stu485Recv.nRegStartAddr+j]=((stu485Recv.Byte_Data[stu485Recv.nRegLen/8]&myPowTwo(i))>0)?1:0;
j++;
}
}
//存回OX
for(i=0;i<OXLength;i++)
{
OX[i]=0;//16位
for(j=0;j<16;j++)
{
//XXArray[i*16+j]=((OX[i]&myPowTwo(j))>0)?1:0;
OX[i]+=XXArray[i*16+j]<<j;
}
}
//实现内存按start位置移动至新区域
/*
主:H 01 0f 00 01 00 17 03 80 80 40 65 6d 0x17=23
从:H 01 0f 00 01 00 17 44 05
*/
ModbusSlave_Tx_Buf[0]=ModbusSlave_localAddr;
ModbusSlave_Tx_Buf[1]=stu485Recv.nCMD;
ModbusSlave_Tx_Buf[2]=USART2_RX_BUF[2];
ModbusSlave_Tx_Buf[3]=USART2_RX_BUF[3];
ModbusSlave_Tx_Buf[4]=USART2_RX_BUF[4];
ModbusSlave_Tx_Buf[5]=USART2_RX_BUF[5];
byteCount=6;
crcData=crc16(ModbusSlave_Tx_Buf,byteCount);
ModbusSlave_Tx_Buf[byteCount] = crcData >> 8;
byteCount++;
ModbusSlave_Tx_Buf[byteCount] = crcData & 0xff;
ModbusSlave_TX_CNT = byteCount + 1;
Modbus_Send_Data(ModbusSlave_Tx_Buf,ModbusSlave_TX_CNT);
}
UsartClearRxBuffer();
}
[17]至于UCOSII及其它的这里就不写了。
自己也是刚学STM32三个月,很多地方都还不懂,甚至有些源程序都是看别人写的。
只是苦于MODBUS_SLAVE_RTU查找的资料不多,就把自己的思路分享出来。v