MODBUS transplant STM32, STM32 do host

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

主机向从机下发读数据指令
从机按照MODBUS协议返回主机的数据
主机接收并CRC验证
数据核对后到读的程序执行数据处理
将数据保存到主机寄存器

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

主机向从机下发写数据指令
从机按照MODBUS协议返回主机的数据
主机接收并CRC验证
数据核对后到读的程序执行数据处理
将数据保存到主机寄存器

Second, the need for hardware configuration

  1. A rearrangement requires the host port, used to see if data is received
  2. 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

Released five original articles · won praise 5 · Views 930

Guess you like

Origin blog.csdn.net/xiaoxiaodawei/article/details/105334085