没有合适的资源?快使用搜索试试~ 我知道了~
首页MODBUS移植STM32,分别配置STM32做从机和主机
MODBUS移植STM32,分别配置STM32做从机和主机
73 下载量 100 浏览量
更新于2023-03-03
5
收藏 946KB PDF 举报
MODBUS移植STM32,分别配置STM32做从机和主机 近期自学了MODBUS通信协议,也从网上找了很多资料,自己也分别做了从机和主机的配置,现在进行配合操作 MCU采用STM32F103C8T6 实现功能,主机分别对从机实现读和写的操作 主机要用到一个外部中断实现发数据的操作 一、配置从机 1.1、配置系统实现定时1MS的功能 初始化系统时钟为72MHZ /****************************************************************************** * @brief 选择外部时钟或者内部时钟并进行倍频 * @par
资源详情
资源推荐
![](https://csdnimg.cn/release/download_crawler_static/14883913/bg1.jpg)
MODBUS移植移植STM32,分别配置分别配置STM32做从机和主机做从机和主机
MODBUS移植移植STM32,分别配置分别配置STM32做从机和主机做从机和主机
近期自学了近期自学了MODBUS通信协议,也从网上找了很多资料,自己也分别做了从机和主机的配置,现在进行配合操作通信协议,也从网上找了很多资料,自己也分别做了从机和主机的配置,现在进行配合操作
MCU采用采用STM32F103C8T6
实现功能,主机分别对从机实现读和写的操作
主机要用到一个外部中断实现发数据的操作
一、配置从机一、配置从机
1.1、配置系统实现定时、配置系统实现定时1MS的功能的功能
初始化系统时钟为72MHZ
/******************************************************************************
* @brief 选择外部时钟或者内部时钟并进行倍频
* @param
RCC_PLLSource:PLL时钟源 :
可以选择:RCC_PLLSource_HSI_Div2、RCC_PLLSource_HSE_Div2、RCC_PLLSource_HSE_Div1
PLLMUL:PLL输入时钟的倍频系数
范围:RCC_CFGR_PLLMULL2~16
PLL时钟根据时钟和倍频来确定,选择内部时钟最高64M
* @retval
******************************************************************************/
void SysClock_Configuration(uint32_t RCC_PLLSource, uint32_t PLLMUL)
{
__IO uint32_t HSEStatus = 0;
RCC_ClocksTypeDef get_rcc_clock;
RCC_DeInit(); // Resets the RCC clock configuration to the default reset state.
if(RCC_PLLSource_HSI_Div2 != RCC_PLLSource) //选择外部时钟
{
RCC_HSEConfig(RCC_HSE_ON); //打开外部时钟
if(RCC_WaitForHSEStartUp() == SUCCESS) //等待外部时钟开启
{
HSEStatus = 1;
}
else
{ //外部时钟打开失败
RCC_PLLSource = RCC_PLLSource_HSI_Div2; //自动选择内部时钟
PLLMUL = RCC_CFGR_PLLMULL16; //配频到64MHZ
RCC_HSEConfig(RCC_HSE_OFF); //关闭外部时钟
RCC_HSICmd(ENABLE); //打开内部时钟
}
}
else
{ //内部时钟
RCC_PLLSource = RCC_PLLSource_HSI_Div2; //自动选择内部时钟
PLLMUL = RCC_CFGR_PLLMULL16; //倍频到64MHZ
RCC_HSEConfig(RCC_HSE_OFF); //关闭外部时钟
RCC_HSICmd(ENABLE); //打开内部时钟
}
RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK(AHB)时钟为系统时钟1分频
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK(APB1)时钟为HCLK时钟2分频
RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK(APB2)时钟为HCLK时钟1分频
//0-24MHz时,取FLASH_Latency_0;
//24-48MHz,取FLASH_Latency_1;
//48-72MHz时,取FLASH_Latency_2。
FLASH_SetLatency(FLASH_Latency_2); //不用到可以不配置
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PLLConfig(RCC_PLLSource, PLLMUL); //PLL时钟配置,时钟源 * PLLMUL
RCC_PLLCmd(ENABLE); //开启PLL时钟,并等待PLL时钟准备好
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //选择PLL时钟为系统时钟
while(RCC_GetSYSCLKSource() != 0x08); //Wait till PLL is used as system clock source
RCC_ClockSecuritySystemCmd(ENABLE); //打开时钟安全系统
RCC_GetClocksFreq(&get_rcc_clock); //仿真的时候就可以在结构体get_rcc_clock中看见各个外设的时钟了
}
配置TIM3时钟
NVIC包含函数
#include “USART.h”
#include “TIMER.h”
// 使用TIM3,对MODBUS协议定时
#define MODBUS_TIM TIM3
#define MODBUS_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MODBUS_TIM_CLK RCC_APB1Periph_TIM3
#define MODBUS_TIM_IRQ TIM3_IRQn
#define MODBUS_TIM_IRQHandler TIM3_IRQHandler
#define MODBUS_TIM_Period (1000-1)
#define MODBUS_TIM_Prescaler (72-1)
/******************************************************************************
* @brief MODBUS_TIM_Config:TIM3初始化
* @param
* @retval
******************************************************************************/
void MODBUS_TIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
MODBUS_TIM_APBxClock_FUN(MODBUS_TIM_CLK, ENABLE); //开启定时器时钟,即内部时钟CK_INT=72M
TIM_TimeBaseStructure.TIM_Period=MODBUS_TIM_Period; //自动重装载寄存器周的值(计数值)
![](https://csdnimg.cn/release/download_crawler_static/14883913/bg2.jpg)
// 累计TIM_Period 个频率后产生一个更新或者中断
// 时钟预分频数为71,则驱动计数器的时钟CK_CNT = CK_INT / (71+1)=1M
TIM_TimeBaseStructure.TIM_Prescaler= MODBUS_TIM_Prescaler;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 时钟分频因子 ,基本定时器没有,不用管
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 重复计数器的值,基本定时器没有,不用管
TIM_TimeBaseInit(MODBUS_TIM,&TIM_TimeBaseStructure); // 初始化定时器
TIM_ClearFlag(MODBUS_TIM,TIM_FLAG_Update); // 清除计数器中断标志位
TIM_ITConfig(MODBUS_TIM,TIM_IT_Update,ENABLE); // 开启计数器中断
TIM_Cmd(MODBUS_TIM, ENABLE); // 使能计数器
}
/******************************************************************************
* @brief ALL_NVIC_Init:配置各个中断优先级
* @param
* @retval
******************************************************************************/
void ALL_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 设置中断组为1
NVIC_InitStructure.NVIC_IRQChannel = MODBUS_TIM_IRQ ; // 设置中断来源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 设置主优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
配置中断函数定时中断函数放到了定时中断函数放到了MODBUS_USART.c中中
/******************************************************************************
* @brief MODBUS_TIM_IRQHandler:MODBUS定时器中断函数
* @param
* @retval
******************************************************************************/
void MODBUS_TIM_IRQHandler (void) //定时器中断函数
{
if ( TIM_GetITStatus( MODBUS_TIM, TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(MODBUS_TIM , TIM_FLAG_Update);//清除中断标志位
}
}
主函数
int main(void)
{
SysClock_Configuration(RCC_PLLSource_HSE_Div1,RCC_CFGR_PLLMULL9);//设置系统时钟,外部设置为72MHZ,内部设置为64MHZ
MODBUS_TIM_Config();
ALL_NVIC_Init();
}
运行程序是否到断点处,现象如下:
1.2、配置系统实现串口接收中断的功能、配置系统实现串口接收中断的功能
使用使用USART2::PA2和和PA3,配置串口,配置串口GPIO口口
// 串口2-USART2
#define MODBUS_USART USART2
#define MODBUS_USART_CLK RCC_APB1Periph_USART2
#define MODBUS_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#define MODBUS_USART_BAUDRATE 9600
// USART GPIO 引脚宏定义
#define MODBUS_USART_GPIO_CLK RCC_APB2Periph_GPIOA
#define MODBUS_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define MODBUS_USART_TX_GPIO_PORT GPIOA
#define MODBUS_USART_TX_GPIO_PIN GPIO_Pin_2
#define MODBUS_USART_RX_GPIO_PORT GPIOA
#define MODBUS_USART_RX_GPIO_PIN GPIO_Pin_3
// USART GPIO 中断
#define MODBUS_USART_IRQ USART2_IRQn
#define MODBUS_USART_IRQHandler USART2_IRQHandler
/******************************************************************************
* @brief MODBUS_USART_Config:MODBUS配置串口模式
* @param 无
* @retval 无
******************************************************************************/
![](https://csdnimg.cn/release/download_crawler_static/14883913/bg3.jpg)
void MODBUS_USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
MODBUS_USART_GPIO_APBxClkCmd(MODBUS_USART_GPIO_CLK, ENABLE); // 打开串口GPIO 的时钟
MODBUS_USART_APBxClkCmd(MODBUS_USART_CLK, ENABLE); // 打开串口外设的时钟
// 将USART1 Tx 的GPIO 配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = MODBUS_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MODBUS_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART Rx 的GPIO 配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = MODBUS_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(MODBUS_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
USART_InitStructure.USART_BaudRate = MODBUS_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(MODBUS_USART, &USART_InitStructure); // 完成串口的初始化配置
USART_ITConfig(MODBUS_USART, USART_IT_RXNE, ENABLE); // 使能串口接收中断
USART_Cmd(MODBUS_USART, ENABLE); // 使能串口
}
/******************************************************************************
* @brief ALL_NVIC_Init:配置各个中断优先级
* @param
* @retval
******************************************************************************/
void ALL_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 设置中断组为1
NVIC_InitStructure.NVIC_IRQChannel = MODBUS_USART_IRQ ; // 设置中断来源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 设置主优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 设置抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
配置串口发送字符函数,为之后发数据做准备
/******************************************************************************
* @brief Usart_SendByte:发送一个字符
* @param
* @retval
******************************************************************************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
USART_SendData(pUSARTx,ch); // 发送一个字节数据到USART
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); // 等待发送数据寄存器为空
}
配置串口接收中断函数
/******************************************************************************
* @brief MODBUS_USART_IRQHandler:MODBUS串口中断函数
* @param
* @retval
******************************************************************************/
void MODBUS_USART_IRQHandler(void)
{
uint8_t ucTemp;
if (USART_GetITStatus(MODBUS_USART,USART_IT_RXNE)!=RESET) //判断是否有数据接收
{}
}
主函数
int main(void)
{
SysClock_Configuration(RCC_PLLSource_HSE_Div1,RCC_CFGR_PLLMULL9);//设置系统时钟,外部设置为72MHZ,内部设置为64MHZ
MODBUS_USART_Config();
ALL_NVIC_Init();
}
用串口助手配置为9600BT/s,发送数据
剩余10页未读,继续阅读
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
安全验证
文档复制为VIP权益,开通VIP直接复制
![](https://csdnimg.cn/release/wenkucmsfe/public/img/green-success.6a4acb44.png)