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)看具体外设寄存器知识,看参考手册
实验中遇到的问题:
- TTL 电平与485电平混接,还好同事发现得早,不然累死也调不出,第1次被鄙视
IM1281B 电能计量模块通讯电平为TTL的
2)使用malloc申请发送缓冲区时,没有释放,导致若干个周期后,程序死机,后来用free释放后正常。
3)有些转态重要的状态可以通过点灯来判断,比如执行某段程序时灯亮,离开时灯灭,有时候还是挺有用的,至少可以
判断程序是否死机,比如主程序中用亮–灭--亮来代表主程序一直在循环执行。
4)中断名称写错,死活进不去中断,还是同事发现的,第2次被鄙视。一定要注意,不然即使中断条件满足了,也进不去中断。
正确写法:void USART3_4_IRQHandler(void),我的写法void USART4_IRQHandler(void)
5)这次工程时新建的,需要添加还多依赖文件,也是第一次完整地从0到1建工程,花费了很长时间,最后一吨的错误,还是要同事来帮忙,原因是官网上依赖文件不能直接用,需要修改,索性用同事已有的文件来替换,就把这个问题解决了。这已算是站在巨人的肩膀上吧。
6)结构体使用时语法错误,编译未报错,使用了一个没有初始化的野指针,所以只要对结构体成员的赋值,即使用野指针的地址就会进入死机,单步跟踪时,直接进入硬件错误while(1)无限循环。还是同事帮助解决,一眼指出问题所在,牛牛牛。深刻理解一句话“嵌入式高手都是C语言高手”
7)总之一句话 ,细节太多,需要自己动手去,才会有感觉。
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)看具体外设寄存器知识,看参考手册
实验中遇到的问题:
- TTL 电平与485电平混接,还好同事发现得早,不然累死也调不出,第1次被鄙视
IM1281B 电能计量模块通讯电平为TTL的
2)使用malloc申请发送缓冲区时,没有释放,导致若干个周期后,程序死机,后来用free释放后正常。
3)有些转态重要的状态可以通过点灯来判断,比如执行某段程序时灯亮,离开时灯灭,有时候还是挺有用的,至少可以
判断程序是否死机,比如主程序中用亮–灭--亮来代表主程序一直在循环执行。
4)中断名称写错,死活进不去中断,还是同事发现的,第2次被鄙视。一定要注意,不然即使中断条件满足了,也进不去中断。
正确写法:void USART3_4_IRQHandler(void),我的写法void USART4_IRQHandler(void)
5)这次工程时新建的,需要添加还多依赖文件,也是第一次完整地从0到1建工程,花费了很长时间,最后一吨的错误,还是要同事来帮忙,原因是官网上依赖文件不能直接用,需要修改,索性用同事已有的文件来替换,就把这个问题解决了。这已算是站在巨人的肩膀上吧。
6)结构体使用时语法错误,编译未报错,使用了一个没有初始化的野指针,所以只要对结构体成员的赋值,即使用野指针的地址就会进入死机,单步跟踪时,直接进入硬件错误while(1)无限循环。还是同事帮助解决,一眼指出问题所在,牛牛牛。深刻理解一句话“嵌入式高手都是C语言高手”
7)总之一句话 ,细节太多,需要自己动手去,才会有感觉。
举报