STM32F103RCT6开发板M3单片机教程03--usart串口通信
本帖最后由 sunsili 于 2023-12-12 13:53 编辑STM32F103RCT6开发板M3单片机教程03--usart串口通信
首先了解编译调试硬件连接,查看原理图
STM32F103RCT6开发板用Jlink供电,USB转串口板电脑USB供电,那么连接只需3线
* TXD(PB9) -> USB转串口板RXD
* RXD(PB10) -> USB转串口T板XD
* GND -> USB转串口板GND
[*]复制上节工程文件夹打开(这个方法比较方便)
[*]新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑
STM32F103RCT6开发板M3单片机教程03--usart串口通信
首先了解编译调试硬件连接,查看原理图
复制上节工程文件夹打开(这个方法比较方便)
新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑
新建源文件SysTick.h,并编辑
编辑main.c
编译调试
/**********************************************************************************
* 文件名:usart.c
* 描述 :usart1 应用函数库
* 实验平台:SUN_STM32F1板
* 硬件连接:TXD(PB9)-> USB转串口板RXD
* RXD(PB10) -> USB转串口T板XD
* GND -> USB转串口板GND
* 库版本:ST_v3.5
* Version Date Auther Reversed History
----------------------------------------------------------------------------
V1.0.0 2021-11-07Lojam FanFisrt Created
* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com
**********************************************************************************/
#include "usart.h"
vu8 Usart1_R_Buff; //串口1数据接收缓冲区
vu8 Usart1_R_State=0; //串口1接收状态
vu16 Usart1_R_Count=0; //当前接收数据的字节数
/*******************************************************************************
* 函数名: USART1_Init_Config
* 描述 : USART1初始化配置
* 输入 : bound:波特率(常用:2400、4800、9600、19200、38400、115200等)
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void USART1_Init_Config(u32 bound)
{
GPIO_InitTypeDefGPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDefNVIC_InitStructure;
/*使能USART1和GPIOA外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
/*复位串口1*/
USART_DeInit(USART1);
/*USART1_GPIO初始化设置*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1_TXD(PA.9)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚输出最大速率为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数中的GPIO初始化函数,初始化USART1_TXD(PA.9)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RXD(PA.10)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数中的GPIO初始化函数,初始化USART1_RXD(PA.10)
/*USART1 初始化设置*/
USART_InitStructure.USART_BaudRate = bound; //设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //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(USART1, &USART_InitStructure); //初始化串口1
/*Usart1 NVIC配置*/
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能串口1接收中断
USART_Cmd(USART1, ENABLE); //使能串口
USART_ClearFlag(USART1, USART_FLAG_TC); //清除发送完成标志
}
/*******************************************************************************
* 函数名: USART_SendData
* 描述 : USART1发送数据缓冲区数据
* 输入 : *buff:数据缓冲区指针,len:发送数据长度
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void USART1_SendData(u8* buff, u16 len)
{
u16 i;
for(i=0; i<len; i++)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1 ,buff);
}
}
/*******************************************************************************
* 函数名: USART1_IRQHandler
* 描述 : 串口1中断服务程序
* 输入 : 无
* 返回 : 无
* 说明 : 1)、只启动了USART1中断接收,未启动USART1中断发送。
* 2)、接收到0x0d 0x0a(回车、"\r\n")代表帧数据接收完成
*******************************************************************************/
void USART1_IRQHandler(void)
{
u8 Res=0;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据(USART1->DR)
Usart1_R_Buff = Res;
if(Usart1_R_State == 0)//数据接收未完成
{
if(Res == 0x0d)//接收到0x0d,下一个字节接收到0x0a则接收完成
{
Usart1_R_State =2;
}
}
else if(Usart1_R_State == 2)
{
if(Res == 0x0a)//上一个字节接收到0x0d,这个字节接收到oxoa则接收完成
{
Usart1_R_State =1;//数据接收完成
}
else//接收错误
{
Usart1_R_State =0;
Usart1_R_Count =0;
}
}
if(Usart1_R_Count >= USART1_REC_MAXLEN)//接收数据长度走出接收数据缓冲区
{
if((Usart1_R_Buff != 0x0d) || (Usart1_R_Buff != 0x0a))
{
Usart1_R_Count =0;
Usart1_R_State =0;
}
}
}
}
/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
******************** END OF FILE usart.c *******************/
[*]新建源文件usart.h,并编辑
#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"
#include <stdio.h>
#define USART1_REC_MAXLEN 200 //最大接收数据长度
void USART1_Init_Config(u32 bound);
void USART1_SendData(u8* buff, u16 len);
//int fputc(int ch, FILE *f);
//void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);
#endif
/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
******************** END OF FILE usart.h *******************/
[*]编辑main.c
/**********************************************************************************
* Sun STM32 mini Demo
* Description
Uart Demo
* Version Date Auther Reversed History
----------------------------------------------------------------------------
V1.0.0 2021-11-07Lojam FanFisrt Created
* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com
**********************************************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "SysTick.h"
#include "led.h"
#include <stdio.h>
extern vu8 Usart1_R_Buff; //串口1数据接收缓冲区
extern vu8 Usart1_R_State; //串口1接收状态
extern vu16 Usart1_R_Count; //当前接收数据的字节数
/*******************************************************************************
* 函数名: main
* 描述 : 主函数,用户程序从main函数开始运行
* 输入 : 无
* 输出 : 无
* 返回值: int:返回值为一个16位整形数
* 说明 : 无
*******************************************************************************/
int main(void)
{
SysTick_Init_Config();
USART1_Init_Config(115200);//USART1初始化配置
LED_GPIO_Config();
printf ("*===================================================*\n");
printf ("**Name: Sun STM32 mini Demo Code. *************\n");
printf ("** (C) Sunshine Silicon Corporation *************\n");
printf ("**Website: http://www.sunsili.com *************\n");
printf ("** E-Mail : fan@sunsili.com *************\n");
printf ("*===================================================*\n");
printf ("* Sun STM32 mini uart transmit the same data to PC .*\n");
while (1)
{
if(Usart1_R_State == 1)//一帧数据接收完成
{
USART1_SendData((u8 *)Usart1_R_Buff, Usart1_R_Count); //USART1发送数据缓冲区数据(发送刚接收完成的一帧数据)
Usart1_R_State =0;
Usart1_R_Count =0;
}
printf("Hello Sunshine Silicon!\r");
LED4_ON();
Delay_nMs(500);
LED4_OFF();
Delay_nMs(500);
}
}
/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
******************** END OF FILE main.c *******************/
[*]编译调试
方法不再重复,经过前两节练习,大家应该是会了.
但发现程序不跑了,单调试发现程序卡在printf不动了。为什么呢?因为MCU不像电脑只要添加stdio.h, 就能用printf。MCU要重定向c库函数printf到USART1(不一定USART1,实际用哪个定义到哪个),标准库代码内容还会被优化掉,编译时不输出。如何让它跑起来了呢。
在usart.c中添加函数
///重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到USART1 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return (ch);
}
///重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
/* 等待串口1输入数据 */
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}
设置编译时,加入MCU适用标准库函数
再次编译调试一切如愿。符合我们当初的设计。
工程源码(回复后可下载)
**** Hidden Message *****
支持一下 试一下 谢谢分享! 感谢分享! huoquyuanma STM32F103RCT6开发板M3单片机教程03--usart串口通信 感谢分享
页:
[1]