Modbus是一种串行通信协议,是Modicon于1979年,为使用可编程逻辑控制器(PLC)而发表的。Modbus是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式。Modbus比其他通信协议使用的更广泛的主要原因有:
【1】公开发表并且无版税要求
【2】相对容易的工业网络部署
【3】对供应商来说,修改移动原生的位元或字节没有很多限制
1、实现f103作为从机,上位机作为主机通信(从站程序)。
1.1 配置时钟
作为保证串口接收数据完整。
//通用定时器3中断初始化
//APB1为SYSCLK的2分频,即36M,因此定时器时钟为APB1的2倍频,即72M
//arr:自动重装值
//psc:时钟分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能时钟
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; /设置用来作为TIMx时钟频率数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); /使能指定的TIM3中断,允许更新中断
//中断优先级NVIC配置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定时器3中断服务程序,100us
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清理TIMx更新中断标志
if(time3_usart1<=200)
time3_usart1++;
if(time3_usart2<=200)
time3_usart2++;
if(time3_usart3<=5000)
time3_usart3++;
}
}
1.2 配置串口USART
配置使用到串口,用于实际的通信端口。
1.2.1 串口优先级配置
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param ÎÞ
* @retval ÎÞ
*/
static void NVIC_usart1_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/*配置USART为中断源*/
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART1_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/*初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
static void NVIC_usart2_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART2_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
1.2.2 串口初始化
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART1_GPIO_APBxClkCmd(DEBUG_USART1_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART1_APBxClkCmd(DEBUG_USART1_CLK, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART1_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART1_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART1_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART1_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStr