MODBUS learn, do Host Configuration STM32
Before learning can look at this article from my machine configuration article.
First, implement the principle of
1.1, to the host, and receives data change their slave register data from the machine-readable data
1.1.1 Programming
void Modbud_fun3(void)
{
unsigned int Regadd=0,i=0,j,Reglen;
Reglen=modbus.rcbuf[2]; //得到读取的寄存器的数量
for(i=0;i<Reglen;i++) //处理读取的数据保存到主机相应寄存器
{ //数据从寄存器的第一个保存到指定数量
Reg[Regadd]=modbus.rcbuf[3+i]*256; //将数据高位保存寄存器
Usart_SendByte( DEBUG1_USART,Reg[Regadd]/256); //发送到另一个串口显示
i++; //数据增加,处理低位
Reg[Regadd]=Reg[Regadd]+modbus.rcbuf[i+3]; //发送到另一个串口显示
Usart_SendByte( DEBUG1_USART,Reg[Regadd]%256); //将数据低位保存寄存器
Regadd++; //处理完高位和低位数据,进行下一个数据
}
}
1.1.2 Design Flow
1.2, write data to the host machine, and receives change data from their own native data register
1.2.1 Programming
void Modbud_fun6()
{
unsigned int Regadd,i=0,crc,j,val;
Regadd=modbus.rcbuf[2]*256+modbus.rcbuf[3]; //得到要更改寄存器的地址
Reg[Regadd]=modbus.rcbuf[4]*256+modbus.rcbuf[5]; //将从机修改的数据再保存到主机寄存器中
Usart_SendByte( DEBUG1_USART,Reg[Regadd]/256); //另一个串口显示修改的数据
Usart_SendByte( DEBUG1_USART,Reg[Regadd]%256); //另一个串口显示修改的数据
}
1.2.2 Design Flow
Second, the need for hardware configuration
- A rearrangement requires the host port, used to see if data is received
- We need to configure an external interrupt for implementing the host machine to read data from or write data
2.1, configure a new serial
Configuring PA9 and PA10 as a new serial port
void USART_Config(void)
{
DEBUG1_USART_GPIO_APBxClkCmd(DEBUG1_USART_GPIO_CLK, ENABLE); // 打开串口GPIO 的时钟
DEBUG1_USART_APBxClkCmd(DEBUG1_USART_CLK, ENABLE); // 打开串口外设的时钟
// 将USART2 Tx 的GPIO 配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG1_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG1_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART2 Rx 的GPIO 配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG1_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG1_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
USART_InitStructure.USART_BaudRate = DEBUG1_USART_BAUDRATE; // 配置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 配置 针数据字长
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 配置停止位
USART_InitStructure.USART_Parity = USART_Parity_No ; // 配置校验位
USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None; // 配置硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 配置工作模式,收发一起
USART_Init(DEBUG1_USART, &USART_InitStructure); // 完成串口的初始化配置
USART_ITConfig(DEBUG1_USART, USART_IT_RXNE, ENABLE); // 使能串口接收中断
USART_Cmd(DEBUG1_USART, ENABLE); // 使能串口
}
2.2, placed external interruption
PA0 configured as an external interrupt , the basic configuration of the GPIO port
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(KEY_UP_INT_GPIO_CLK,ENABLE); //开启按键GPIO 口的时钟
/*--------------------------KEY1 配置---------------------*/
GPIO_InitStructure.GPIO_Pin = KEY_UP_INT_GPIO_PIN; // 选择按键用到的GPIO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 配置为下拉输入,因为浮空输入其他的管脚对他的干扰很大
GPIO_Init(KEY_UP_INT_GPIO_PORT, &GPIO_InitStructure);
GPIO_EXTILineConfig(KEY_UP_INT_EXTI_PORTSOURCE,KEY_UP_INT_EXTI_PINSOURCE);// 选择EXTI 的信号源
EXTI_InitStructure.EXTI_Line = KEY_UP_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // EXTI 为中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿中断
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断
EXTI_Init(&EXTI_InitStructure);
}
To configure this place GPIO pull-down or pull-up input, because the floating prone to instability, it will cause external interference
GPIO external interrupt header file
//引脚定义
#define KEY_UP_INT_GPIO_PORT GPIOA
#define KEY_UP_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY_UP_INT_GPIO_PIN GPIO_Pin_0
#define KEY_UP_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY_UP_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY_UP_INT_EXTI_LINE EXTI_Line0
#define KEY_UP_INT_EXTI_IRQ EXTI0_IRQn
#define KEY_UP_IRQHandler EXTI0_IRQHandler
void EXTI_Key_Config(void);
External interrupt function
void KEY_UP_IRQHandler(void)
{
if (EXTI_GetITStatus(KEY_UP_INT_EXTI_LINE) != RESET) //确保是否产生了EXTI Line 中断
{
Usart_SendByte( DEBUG1_USART,modbus.myadd);//发送从机数据
Usart_SendByte( DEBUG1_USART,0x03);
Usart_SendByte( DEBUG1_USART,0x00);
Usart_SendByte( DEBUG1_USART,0x00);
Usart_SendByte( DEBUG1_USART,0x00);
Usart_SendByte( DEBUG1_USART,0x02);
Usart_SendByte( DEBUG1_USART,0xC4);
Usart_SendByte( DEBUG1_USART,0x5E);
Usart_SendByte( DEBUG_USART,modbus.myadd);//发送到新开的串口用于调试查看
Usart_SendByte( DEBUG_USART,0x03);
Usart_SendByte( DEBUG_USART,0x00);
Usart_SendByte( DEBUG_USART,0x00);
Usart_SendByte( DEBUG_USART,0x00);
Usart_SendByte( DEBUG_USART,0x02);
Usart_SendByte( DEBUG_USART,0xC4);
Usart_SendByte( DEBUG_USART,0x5E);
EXTI_ClearITPendingBit(KEY_UP_INT_EXTI_LINE); //清除中断标志位
}
}
This place is no software debouncing, just for debugging, practice should be added debounce