完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
1、内容
使用 开发板 串口4进行通信,开发板做ModbusRTU主机,读取电能表参数。 2、所需硬件 1)开发板一块:STM32f072RBT6、JLlink下载线 2)IM1281B 电能计量模块一块 连接线若干 3、实验步骤 1)对使用的端口(包括串口,普通GPIO口)进行初始化,其中串口初始化的内容主要包括时钟配置、使能。 主要通过三个结构体来实现USART_InitTypeDef,NVIC_InitTypeDef, GPIO_InitTypeDef。 这三个结构体的主要作用如下: USART_InitTypeDef: 对ModbusRTU协议所需要的的通讯参数,比如波特率,校验位,停止位等进行配置,开启串口中断等,我觉得一般都要开启串口中断,因为要使用串口中断函数来接收从机的发来的数据 配置代码如下: /* USARTx configuration ----------------------------------------------------*/ USART_InitTypeDef USART_InitStruct; USART_InitStruct.USART_BaudRate = Frequency; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART4, &USART_InitStruct); USART_ITConfig(USART4, USART_IT_RXNE, ENABLE);//使能USART中断 USART_Cmd(USART4, ENABLE);/* Enable USART */ /* Enable USART */ USART_Cmd(USART4, ENABLE); NVIC_InitTypeDef: 配置中断名称和中断等级等 配置代码如下: /* NVIC configuration: Enable the USARTx Interrupt---------------------------------------------------- */ NVIC_InitStructure.NVIC_IRQChannel = USART3_4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断 GPIO_InitTypeDef: 配置GPIO端口的模式,比如使用到哪些端口定义,输入还是输出,如果是输出的话,最大速度是多少,是推挽输出还是上拉输出等 本例中使用的是 PA.0和PA.1, /* Configure USART Tx and Rx as alternate function push-pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA, &GPIO_InitStructure); 整体USART.C代码 #include "stm32f0xx.h" #include "USART.h" u16 ch_tx_SendIndex,ch_tx_SendLength,ch_rx_RecvIndex,ch_rx_RecvLength,ch_RXFLAG; u8 ch_tx_buf[60];用于发送主机发送RTU指令,即先把要发送的字节放在这个缓冲数组内,再通过串口发送函数USART_SendData发送 给从机 u8 ch_rx_buf[60];用于存放从机发来的数据, void USART3_Init(uint32_t Frequency) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_InitTypeDef USART_InitStruct; /* config USART3 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); /* USART3 GPIO config */ /* Configure USART3 Tx as alternate function push-pull */ GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_1); GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART3_4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* USART3 mode config */ USART_InitStruct.USART_BaudRate = Frequency; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART3, &USART_InitStruct); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_Cmd(USART3, ENABLE); } void USART4_Init(uint32_t Frequency) //PA.0 Tx , PA.1Rx { USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIO clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Enable USART clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4 , ENABLE); /* Connect PXx to USARTx_Tx */ GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_4); /* Connect PXx to USARTx_Rx */ GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_4); /* Configure USART Tx and Rx as alternate function push-pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA, &GPIO_InitStructure); /* USARTx configuration ---------------------------------------------------- - USARTx configured as follow: - BaudRate = Frequency - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled */ USART_InitStruct.USART_BaudRate = Frequency; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; //USART_InitStruct.USART_Parity = USART_Parity_Even ; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART4, &USART_InitStruct); USART_ITConfig(USART4, USART_IT_RXNE, ENABLE);//使能USART中断 USART_Cmd(USART4, ENABLE);/* Enable USART */ /* NVIC configuration: Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断 NVIC_Init(&NVIC_InitStructure); /* Enable USART */ USART_Cmd(USART4, ENABLE); } 2)在MODBUS.C中组织主机发宋给从机的数据(参考正点原子资料) void mp_send_data(u8* buf, u16 len) { u16 i=0; for(i=0;i while((USART4->ISR&0X40)==0); //等待上一次串口数据发送完成 USART4->TDR=buf; //发送数据将待发送的数据放入串口的发送数据寄存器中即可,硬件会自动发送 } } struct m_frame *fx;//定义一个主机发送到从机的通讯帧结构 //打包一帧数据,并发送 //fx:指向需要打包的帧 //发送 01 03 00 48 00 08 C4 1A //接收 01 03 20 Data01_Data08 1B C2 void mb_packsend_frame(struct m_frame *fx) { u16 framelen=0; //打包后的帧长度 // u8 sendbuf[8]; //发送缓冲区,待发送的数据先处理好放在这块区内,然后确定好长度framelen和起始地址&sendbuf[0]后,利用senddata从串口中循环发送。 u8* sendbuf; fx->address=0x01; fx->function=0x03; fx->Start_address_Hi=0x00; fx->Start_address_Li=0x48; fx->Quantity_Registers_Hi=0x00; fx->Quantity_Registers_Li=0x08; fx->CRC16_Hi=0xC4; fx->CRC16_Li=0x1A; fx->Framelen=0x08; framelen=fx->Framelen; sendbuf=(u8*)malloc(framelen); //申请发送数据缓冲区内存 sendbuf[0]=fx->address; sendbuf[1]=fx->function; sendbuf[2]=fx->Start_address_Hi; sendbuf[3]=fx->Start_address_Li; sendbuf[4]=fx->Quantity_Registers_Hi; sendbuf[5]=fx->Quantity_Registers_Li; sendbuf[6]=fx->CRC16_Hi; sendbuf[7]=fx->CRC16_Li; mp_send_data(sendbuf,framelen); //发送这一帧数据 free(sendbuf);//释放发送数据缓冲区内存,如果不释放吗,就会出现运行一段时间死机的现象 } 3)在串口中断中把从机返回的数据放到接收缓冲区的数组里面 void USART3_4_IRQHandler(void) { if(USART_GetITStatus(USART4, USART_IT_RXNE) != RESET) { // USART4->TDR=USART4->RDR;//调试代码 :自收自发,收到什么,发送什么 if( ch_rx_RecvIndex<60) { ch_rx_buf[ch_rx_RecvIndex]=USART4->RDR; ch_rx_RecvIndex++; } else ch_rx_RecvIndex=0; } } 最后上一份实际图,代表这个实验暂时告一段落。这个实验我从5月份断断续续调到今天。 发送 01 03 00 48 00 08 C4 1A 接收 01 03 20 Data01~Data08 1B C2 备注: 1)F0的固件库函数使用网上没有找到,我参考的的是F1的固件库手册。 2)F0外设参数初始化模板可以参考开发板历程,也可以在ST逛网下载外设库,里面有一个帮助手册也可以看到。 文件是以chm结尾的文件。具体名称是stm32f0xx_stdperiph_lib_um.chm。参考的是 STM32F0xx_StdPeriph_Lib_V1.5.0。 3)开发F0单片机必备的手册 ,根据我的老师们讲,手册在手,天下我有。 1)想知道管脚定义,时钟树,内存图:看数据手册(Datasheet-production data) 2)想知道操作外设的库函数怎么用:看固件库手册 3)至于编程手册:还有看过,感觉很有用,下次分解 4)看具体外设寄存器知识,看参考手册 实验中遇到的问题:
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 09:19 , Processed in 0.661387 second(s), Total 46, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号