《STM32从零开始学习历程》@EnzoReventon
最近开始接触了STM32F4xx系列单片机,对于我这个从零开始学习的小白来说,可谓困难重重,我是跟着“正点原子”和“野火”这两个STM32培训机构来学习的,开发板买的是“正点原子”F4系列,视频在之前学习过程中主要看的是“正点原子”的,现在主要参考“野火”的视频,个人感觉“正点原子”的程序框架和“野火”的视频比较适合我,因此两者结合了一下,各取所长吧。
正因为在学习过程中困难重重,才让我下定决心把自己所遇到的困难以及解决困难的方法全部记录下来,也算是学习笔记,与大家分享,有不足之处还请各位大佬多多指教。
在开始之前,我觉得资料非常重要,不管是官方的还是非官方的,一定要保证这些资料在你电脑能够最快开启的位置。
软件:Keil μVision5 v5.33(MDK5),串口助手XCOM V2.6
环境:Windows10 Enterprise x64
芯片:STM32F406ZGT6
设备:正点原子STM32F4探索者开发板
仿真器:ST-Link
参考手册:
[野火EmbedFire]《STM32库开发实战指南——基于野火霸天虎开发板》
[正点原子]STM32F4开发指南-库函数版本_V1.2
[ST]《STM32F4xx中文参考手册》
[ST]《STM32F407xx》
一些usart,串口通讯的理论知识在这里就不详细介绍了。 有需要了解同学可以看看其他文章,他们讲的很详细很到位。
通过串口助手给STM32发送字符串,STM32能够将所接收到的字符串返回。
表3-1 STM32F407ZGT6芯片USART引脚表
在开发板上找到U17,发现USART1串口就是USB232口,使用数据线将其与电脑连接即可。
如果需要使用其他串口,也是如此,查阅硬件手册,找到相应的串口即可。
在正点原子开发板上默认将PA9(TX)与RXD / PA10(RX)与TXD相连接了。如下图所示:
PA9 PA10 与 TX RX连接图 使用跳帽连接
由于本文是使用USART1 PB6/PB7为引脚,所以需要使用杜邦线将PB6(TX)与RXD / PB7(RX)与TXD相连接。如下图所示:
PB6 PB7 与 TX RX连接图 使用杜邦线连接
至此,通讯口与引脚的接线已经完成。
对于程序而言,正点原子与野火的案例程序我都进行了分析,个人感觉对野火的案例程序比较好理解(可能是我比较菜,正点原子的案例程序还在进一步消化中),因此本文的程序设计是基于野火的案例程序。
表4-1 一些常用的中断标志位
中断事件 | 事件标志 | 使能控制位 |
---|---|---|
发送数据寄存器为空 | TXE | TXEIE |
CTS标志 | CTS | CTSIE |
发送完成 | TC | TCIE |
准备好读取接收到的数据 | RXNE | RXNEIE |
检测到上溢错误 | ORE | RXNEIE |
检测到空闲线路 | IDLE | IDLEIE |
奇偶校验错误 | PE | PEIE |
断路标志 | LBD | LBDIE |
多缓冲通信中的噪声标志、上溢错误和帧错误 | NF/ORE/FE | EIE |
1.初始化函数
void uart_init(u32 bound)
{
============================================================
//GPIO端口设置 配置结构体名称
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
============================================================
//使能GPIOA时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
============================================================
//串口1对应引脚复用映射 GPIOB6复用为USART1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_USART1);
//GPIOB7复用为USART1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1);
//USART1端口配置
//GPIOA2与GPIOA3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
//复用功能
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//速度50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//推挽复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//上拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//初始化PA9,PA10
GPIO_Init(GPIOB,&GPIO_InitStructure);
============================================================
//USART1 初始化设置
//波特率设置
USART_InitStructure.USART_BaudRate = bound;
//字长为8位数据格式
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;
//初始化串口1
USART_Init(USART1, &USART_InitStructure);
============================================================
//使能串口1
USART_Cmd(USART1, ENABLE);
//开启相关中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
============================================================
//Usart1 NVIC 配置
//串口1中断通道
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
//子优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;
//IRQ通道使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//根据指定的参数初始化NVIC寄存器、
NVIC_Init(&NVIC_InitStructure);
}
void USART_SendByte(USART_TypeDef * pUSARTx, uint8_t ch)
{
USART_SendData(pUSARTx,ch);
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET)
{ }
}
void USART_SendString(USART_TypeDef * pUSARTx, char *str)
{
unsigned int k = 0;
do{
USART_SendByte(pUSARTx, *(str + k));
k++;
} while(*(str + k) != '\0');
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET)
{ }
void USART1_IRQHandler(void) //串口1中断服务程序
{
uint8_t temp;
if ( USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET)
{
temp = USART_ReceiveData(USART1);
USART_SendData(USART1,temp);
}
}
int main(void)
{
//设置系统中断优先级分组2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//延时初始化
delay_init(168);
//串口初始化波特率为115200
uart_init(115200);
USART_SendString(USART1, "This is a test!");
while(1)
{ }
}
将程序编译下载到设备,打开XCOM串口调试软件。
首先会出现主程序中发送的"This is a test!"。
在发送窗口中输入字符串,点击发送。
至此,试验结束。
这个实验不难,新手入门还是建议代码一行一行的敲一下,了解下底层的知识。
其次,需要学会查阅各种手册,不管是硬件还是软件,都要进行充分的研读。
我在这次实验完成之前,没有充分查阅硬件手册,导致PB6/PB7配置好了一直接收不到数据,后来发现没有拔掉PA9/PA10的跳帽,也没有将USART1 的TX RX与PB6/PB7相互连接,以为仅需要编写代码就可以实现串口之间的切换,实践证明,玩转嵌入式是需要软硬结合的!
此外,本人还在学习中,如有不足请大佬们多多指教,如有侵权立删!