本节主要讲解串口1的收发通信功能,接收数据以换行符为结束标志(\r\n)。
串口的详细解说可参考《STM32F4XXX中文参考手册》,资料有详细的讲解和说明,文档可跟作者联系索取,或百度搜索也可。
话不多说,开始写代码吧。。
一、打开STM32CubeMX选择对应的芯片型号,后进入开发界面; 详细步骤可参考: (1)<STM32>STM32CubeMX-工程创建及定时器控制LED灯闪烁(2) (2)<STM32>STM32CubeMX-基础工程创建及LED灯控制 (1)
二、开始配置操作 1、配置RCC,即晶振的选择配置; 选择"Pinout&Configuration"->“System Core”->“RCC”,如下图步骤1、2、3; High Speed Clock(HSE):表示外部高速晶振; High Speed Clock(HSE):表示外部低速晶振,使用RTC实时时钟是一般用这个; 在步骤4、5可选择晶振的配型,“BYPASS Clock Source”和“Crystal/Ceramic Resonator”两种,第一个是旁路时钟源,第二个是晶体/陶瓷谐振器,一般电路使用的是“Crystal/Ceramic Resonator”。 本教程作者选用的高速和低速都是“Crystal/Ceramic Resonator”。 2、配置SYS,即DEBUG的方式选择
选择"Pinout&Configuration"->“System Core”->“SYS”,如下图步骤1、2、3; 下图步骤4则是选择Debug的方式,一般选择SDW的方式能满足使用,如果想用JTAG也可选择JTAG。
本教程在这里作者选中SDW的方式即“Serial Wire”。 3、配置串口参数 本次使用的是串口1,串口1默认引脚是PA9和PA10; 配置参数入上图所示: 步骤1,2,3:选择到对应的配置串口,选择后出现中间部分框图; 步骤4:可选择项分为一下几种: 1)Asynchronous:异步通信 2)synchronous :同步通信 3)single Wire(Half-Duplex):单线(半双工)通信 4)Multiprocessor Communication:多处理器通信 5)LrDA :红外通信 6)LIN :LIN通信 7)SmartCard:智能卡
本次教程选用Asynchronous:异步通信即可,主要是做普通串口使用;
步骤5:串口参数配置: 步骤6:参数设置,包含:波特率:115200、字长:8位、校验位:无、停止位:1位; 步骤7:数据方向:接收和发送 、 16位采样; 步骤8:勾选中断使能
三、工程配置 1、时钟配置: 如上图所示:选择 步骤1选项,然后再步骤2位置输入系统的主频时钟值,回车确认即可,自动完成。F4系列一般是 168或180,F1系列一般是72.
2、工程输出属性配置 工程属性配置,如上图所示: 步骤1、2:进入配置界面; 步骤3:输入工程名称; 步骤4:工程存放的目录路径; 步骤5:工程的DMK 和对应的版本选择;使用Keil5的选择”MDK-ARM“ 步骤6:堆栈大小的设置,一般用的不大的话,使用默认即可。
3、代码生成器配置 代码生成器配置如上图: 步骤1、2:进入配置界面; 步骤3:拷贝所以使用到的库到工程中; 步骤4:生成单独的.c和.h文件,方便后续功能添加修改管理; 建议初学者按上图配置即可。
四、代码生成和功能补充测试
1、代码生成 在以上所有都配置完成后,电机上图 红色1位置,即可生成代码,并在弹出的对话框选择“Open Project”打开项目。
2、代码补充 在打开的工程中补充修改完善代码; 补充修改代码分别在4个文件中进行,根据配置后生成的工程目录如下图所示: 补充修改完善代码分别对应的文件是“main.c”、“stm32f4xx_it.c”、“usart.c"和"usart.h”,这四个文件,下面分别说明具体修改内容。
1)"stm32f4xx_it.c"文件修改:主要是注释掉,自动生成的串口中断函数,按找下图注释掉,具体如下: 2)"usart.h"文件修改:主要是添加一些定义等,具体如下所示:
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
extern UART_HandleTypeDef huart1;
#define USART_REC_LEN 200
#define RXBUFFERSIZE 1
extern uint8_t USART_RX_BUF[USART_REC_LEN];
extern uint16_t USART_RX_STA;
void MX_USART1_UART_Init(void);
uint8_t API_USART1_SendData(uint8_t *pData,uint16_t len);
#ifdef __cplusplus
}
#endif
#endif
3)"usart.c"修改:主要是定义变量、增加中断处理函数、中断公共回调函数、以及重定向输出函数(用以使用printf),还有一个则是在初始化函数内添加接收中断buf。
变量定义如下:
#include "stdio.h"
uint8_t USART_RX_BUF[USART_REC_LEN];
uint16_t USART_RX_STA=0;
uint8_t aRxBuffer[RXBUFFERSIZE];
初始化函数内添加接收中断buf:如下:
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
}
中断函数如下:
void USART1_IRQHandler(void)
{
uint32_t timeout=0;
uint32_t maxDelay=0x1FFFF;
HAL_UART_IRQHandler(&huart1);
timeout=0;
while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)
{
timeout++;
if(timeout>maxDelay) break;
}
timeout=0;
while(HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
timeout++;
if(timeout>maxDelay) break;
}
}
中断公共回调函数如下:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
if((USART_RX_STA&0x8000)==0)
{
if(USART_RX_STA&0x4000)
{
if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;
else USART_RX_STA|=0x8000;
}
else
{
if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
}
}
}
}
}
发送函数如下:
uint8_t API_USART1_SendData(uint8_t *pData,uint16_t len)
{
uint8_t ret = 0;
if(HAL_UART_Transmit(&huart1,pData,len,5000) != HAL_OK)
{
ret = 1;
}
return ret;
}
重定向输出如下:
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
**代码放置位置,建议放在有标识的位置如“USER CODE BEGIN X”和“USER CODE END X”,其中X代表数值1.2.3…;将代码放置于这两句话之间的效果就是,如果重新用STM32CubeMX重新配置这个工程,那么在这两句话之间书写的代码,不会被清理掉,会保留;如果在之两句话之外的位置书写代码,则会被清理掉。**本次工程放置效果如下图所示: 4)“main.c”文件修改:主要是对输入输出数据进行操作,具体如下:
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void SystemClock_Config(void);
int main(void)
{
uint16_t RevLen;
uint8_t i;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
if(USART_RX_STA&0x8000)
{
RevLen = USART_RX_STA&0x3fff;
printf("接收数据长度为:%d \r\n",RevLen);
printf("接收数据内容为:%s \r\n",USART_RX_BUF);
USART_RX_STA=0;
memset(USART_RX_BUF,0,USART_REC_LEN);
}
i++;
if(i>=10)
{
i=0;
printf("请输入数据,以回车键结束\r\n");
}
HAL_Delay(100);
}
}
3、编译代码和下载运行 1)编译:编译后无错误,如下图所示,如果有错误,根据错误修改错误的位置,然后重新编译,直至编译成功。 2)下载:点击下载按钮,等待下载完成即可;如下图: 4、测试
将板子的PA9和PA10 接到串口转TTL模块,并将模块的USB接口接到电脑,然后打开串口调试助手(网上有很多可以下载,或者可以联系作者索要),根据模块识别的串口号,打开对应的串口,注意波特率、数据为、停止位、校验位等参数,要与代码设置的参数保持一致。 有些开发板可能会带有串口转TTL芯片,有的,则直接将对应接口的USB口,接到电脑即可(根据具体使用的开发板情况而定)。
打开串口后,在输入框输入发送的数据如:“123abc”,注意勾选“换行”,并点击发送;可在接收窗口看待对应输出的输出信息; 如下图: 至此串口收发功能以实现; 如有不理解、不明白指出可联系作者; 如有错误遗漏等,还望指教说明,多促进交流;
联系方式:QQ759521350 …本文属原创作品,转载表明出处…
|