|
- #include "RS485.h"
- // 变量定义:
- uint8_t USART_TX_BUF[64]; //串口数据发送缓存数组(最大可发送64字节数据)
- /*******************************************************************************
- 函数名称:Modbus协议CRC校验函数
- 输入参数:buf 指向要校验的数据缓存区基址
- 输入参数:len 要校验的字节数
- 返回参数:CRC 校验结果
- 注意事项:无
- ********************************************************************************/
- static uint16_t CRC_16(uint8_t *buf,uint8_t len)
- {
- uint16_t CRC16 = 0xFFFF;
- uint8_t i, j;
-
- for (i = 0; i < len; i++)
- {
- CRC16 ^= buf[i] ;
- for (j = 0; j < 8; j++)
- {
- if ((CRC16 & 0x0001) != 0){CRC16 = (CRC16>>1)^0xA001;}
- else{CRC16 >>= 1;}
- }
- }
- return CRC16;
- }
- /*******************************************************************************
- 函数名称:RS485数据缓存区初始化函数
- 输入参数:buf 指向要初始化缓存区的基址
- 输入参数:data 要初始化的数值(一般初始化的值为0x00)
- 输入参数:len 要初始化的字节长度
- 返回参数:无
- 注意事项:无
- ********************************************************************************/
- static void Arry_Init(uint8_t *buf,uint8_t data,uint8_t len)
- {
- uint8_t i; //索引变量
- for(i=0;i<len;i++) //执行相应次数的字节空间初始化
- {
- buf[i] = data; //字节空间初始化
- }
- }
- /*******************************************************************************
- 函数名称:RS485串口参数配置函数
- 输入参数:无
- 返回参数:无
- 注意事项:无
- ********************************************************************************/
- void RS485_USART_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO外设初始化结构体
- USART_InitTypeDef USART_InitStructure; //定义USART外设初始化结构体
-
- USART_APBxClkCmd( USART_CLK, ENABLE ); //使能APB2高速USART1外设时钟
- USART_GPIO_APBxClkCmd( USART_GPIO_CLK,ENABLE ); //使能APB2高速GPIOA外设时钟
- RS485_GPIO_APBxClkCmd( RS485_GPIO_CLK,ENABLE ); //使能接收发送引脚时钟
-
- //配置发送引脚Tx
- GPIO_InitStructure.GPIO_Pin = USART_TX_PIN; //配置GPIO端口
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置为复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //端口速度配置为50MHz
- GPIO_Init( USART_TX_PORT,&GPIO_InitStructure ); //端口初始化
-
- //配置接收引脚Rx
- GPIO_InitStructure.GPIO_Pin = USART_RX_PIN; //配置GPIO端口
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //配置为浮空输入
- GPIO_Init(USART_RX_PORT,&GPIO_InitStructure); //端口初始化
-
- //配置接收或发送使能引脚
- GPIO_InitStructure.GPIO_Pin = RS485_GPIO_PIN; //配置GPIO端口
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置为推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //端口速度配置为50MHz
- GPIO_Init( RS485_GPIO_PORT,&GPIO_InitStructure ); //端口初始化
-
- //配置串口外设
- USART_InitStructure.USART_Mode = USART_Mode_Tx; //配置串口为发送模式
- USART_InitStructure.USART_BaudRate = USART_BAUD; //配置串口波特率
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //配置串口硬件控制流
- USART_InitStructure.USART_Parity = USART_Parity_No; //配置校验位为无校验
- USART_InitStructure.USART_StopBits = USART_StopBits_1; //配置串口为一个停止位
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; //八位数据帧模式
- USART_Init(USARTx, &USART_InitStructure); //USART初始化
-
- USART_ClearFlag(USARTx, USART_FLAG_TC); //清除发送完毕标志位TC
-
- USART_Cmd( USARTx,ENABLE ); //使能串口
- RS485_TXorRX_EN( TX_EN ); //接收或发送使能引脚默认为接收状态
- }
- /*******************************************************************************
- 函数名称:RS485串口发送函数
- 输入参数:buf 指向数据发送缓存区的首地址
- 输入参数:len 指定发送的数据长度
- 返回参数:无
- 注意事项:无
- ********************************************************************************/
- void RS485_SendData(uint8_t *buf,uint8_t len)
- {
- uint8_t i = 0; //索引变量
-
- RS485_TXorRX_EN( TX_EN ); //使能为发送模式
- Delay_ms(3);
- for(i=0;i<len;i++) //按照相应长度循环发送数据
- {
- while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET); //检测是否发送完毕
- USART_SendData(USARTx,buf[i]); //将指向的数据发送
- }
- while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET); //检测是否发送完毕
- }
- ///*******************************************************************************
- //函数名称:Modbus协议主机发送0x03(读寄存器)命令函数
- //输入参数:addr 要发送命令的从机设备地址
- //输入参数:startable 要读取的从机寄存器起始地址
- //输入参数:len 要读取的寄存器个数
- //返回参数:无
- //注意事项:无
- //********************************************************************************/
- //void Modbus_Send_0x03Cmd(uint8_t addr,uint16_t startaddr,uint16_t len)
- //{
- // if(len > 0x14){len = 0x14;} //读取的寄存器个数只允许读20个,超出按最大20个读取(寄存器个数的最大值要根据接收缓存区的大小来决定,可人为定义寄存器个数的最大值)
- // USART_TX_BUF[0] = addr; //获取从机设备地址
- // USART_TX_BUF[1] = 0x03; //获取读寄存器功能码(0x03)
- // USART_TX_BUF[2] = (uint8_t)(startaddr>>8); //获取寄存器基址高字节
- // USART_TX_BUF[3] = (uint8_t)(startaddr&0xFF); //获取寄存器基址低字节
- // USART_TX_BUF[4] = (uint8_t)(len>>8); //获取读取寄存器个数高字节
- // USART_TX_BUF[5] = (uint8_t)(len&0xFF); //获取读取寄存器个数低字节
- // ((uint16_t)*(USART_TX_BUF+6)) = CRC_16(USART_TX_BUF,6);//获取发送数据的CRC校验结果
- // RS485_SendData(USART_TX_BUF,8); //发送读寄存器功能命令
- // USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); //发送完毕,开串口接收中断
- //}
- /*******************************************************************************
- 函数名称:Modbus协议主机发送0x06(写单个寄存器)命令函数
- 输入参数:addr 要发送命令的从机设备地址
- 输入参数:startable 要发送的从机寄存器起始地址
- 输入参数:Data 要写入的数据
- 返回参数:无
- 注意事项:无
- ********************************************************************************/
- void Modbus_Send_0x06Cmd(uint8_t addr,uint16_t startaddr,uint16_t Data)
- {
- unsigned short temp;
-
- USART_TX_BUF[0] = addr; //获取从机设备地址
- USART_TX_BUF[1] = 0x06; //获取读寄存器功能码(0x06)
- USART_TX_BUF[2] = (uint8_t)(startaddr>>8); //获取寄存器基址高字节
- USART_TX_BUF[3] = (uint8_t)(startaddr&0xFF); //获取寄存器基址低字节
- USART_TX_BUF[4] = (uint8_t)(Data>>8); //获取写入数据的高字节
- USART_TX_BUF[5] = (uint8_t)(Data&0xFF); //获取写入数据的低字节
- temp = CRC_16( USART_TX_BUF,6 );
- USART_TX_BUF[6] = (uint8_t)(temp&0xFF);
- USART_TX_BUF[7] = (uint8_t)(temp>>8);
- RS485_SendData(USART_TX_BUF,8); //发送读寄存器功能命令
- }
- ///*******************************************************************************
- //函数名称:Modbus协议主机发送0x10(写多个寄存器)命令函数
- //输入参数:addr 要发送命令的从机设备地址
- //输入参数:startable 要写入的从机寄存器起始地址 (范围:0~64)
- //输入参数:len 要写入的寄存器个数 (范围:0~255)
- //输入参数:buf 指向要发送的数据缓存区
- //返回参数:无
- //注意事项:无
- //********************************************************************************/
- //void Modbus_Send_0x10Cmd(uint8_t addr,uint16_t startaddr,uint16_t len,uint16_t *buf)
- //{
- // uint8_t i = 0; //索引变量
- //
- // USART_TX_BUF[0] = addr; //获取从机设备地址
- // USART_TX_BUF[1] = 0x10; //获取写多个寄存器功能码(0x10)
- // USART_TX_BUF[2] = (uint8_t)(startaddr>>8); //获取寄存器基址高字节
- // USART_TX_BUF[3] = (uint8_t)(startaddr&0xFF); //获取寄存器基址低字节
- // USART_TX_BUF[4] = (uint8_t)(len>>8); //获取写入数据寄存器个数高字节
- // USART_TX_BUF[5] = (len&0xFF); //获取写入数据寄存器个数低字节
- // USART_TX_BUF[6] = (uint8_t)(len*2); //获取数据的总字节数
- // for(i=0;i<USART_TX_BUF[5];i++) //循环获取要发送的数据
- // {
- // USART_TX_BUF[7+(i*2)] = (uint8_t)(buf[i]>>8);
- // USART_TX_BUF[8+(i*2)] = (uint8_t)(buf[i]&0xFF);
- // }
- // ((uint16_t)(USART_TX_BUF+(7+USART_TX_BUF[6]))) = CRC_16(USART_TX_BUF,(7+USART_TX_BUF[6])); //获取发送数据的CRC校验结果
- // RS485_SendData(USART_TX_BUF,(9+USART_TX_BUF[6])); //发送写多个寄存器功能命令
- //}
- #include "stm32f10x.h"
- #include "RS485.h"
- #include "Delay.h"
- void GPIO_Cofing( void );
- /*******************************************************************************
- 函数名称:主函数
- 输入参数:无
- 返回参数:无
- 注意事项:无
- ********************************************************************************/
- int main(void)
- {
- Delay_Init();
- RS485_USART_Config();
- GPIO_Cofing();
- while(1)
- {
- Modbus_Send_0x06Cmd(0x01,0x2000,0x0001); //发送电机正转信号
- Delay_ms(20000);
- // Modbus_Send_0x06Cmd(0x01,0x2001,0x0002); //发送电机正转信号
- // Delay_ms(1000);
- }
- }
- void GPIO_Cofing( void )
- {
- GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO外设初始化结构体
-
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE );
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_Init( GPIOA, &GPIO_InitStructure );
-
- GPIO_SetBits( GPIOA, GPIO_Pin_6 );
- Delay_ms(3000);
- }
复制代码
|
|