串口通信(USART)程序代码

本文是STM32F103RCT6与上位机进行串口通信(USART)时的程序代码的笔记总结。文中的代码是从芯片STM32F103ZET6的代码中移植过来的,已经过实验验证,可以正常运行。

一、usart.h 文件

#ifndef __USART_H
#define __USART_H
#include "stdio.h"    
#include "sys.h"

#define USART_REC_LEN        200             //声明最大接收字节数 200
#define EN_USART1_RX             1              //使能(1)/禁止(0)串口1接收
          
extern u8  USART_RX_BUF[USART_REC_LEN];     //声明接收缓冲数组,最大200个字节
extern u16 USART_RX_STA;                       //接收状态标记    
extern UART_HandleTypeDef   UART1_Handler;     //UART句柄

#define RXBUFFERSIZE   1                         //声明缓存大小
extern u8 aRxBuffer[RXBUFFERSIZE];        //声明HAL库的USART接收Buffer


void uart_init(u32 bound);
#endif

二、usart.c 文件

#include "sys.h"
#include "usart.h"    

#if 1
#pragma import(__use_no_semihosting)             //标准库需要的支持函数                 
struct __FILE 

    int handle; 

}; 

FILE __stdout;                                                       //定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 

    x = x; 
}                                                                            //重定义fputc函数 
int fputc(int ch, FILE *f)
{      
    while ((USART1->SR & 0X40) == 0);               //循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
    return ch;
}
#endif 


#if EN_USART1_RX                                              //如果使能了接收 
u8 USART_RX_BUF[USART_REC_LEN];            //接收缓冲,最大USART_REC_LEN个字节.
u16 USART_RX_STA=0;                                       //接收状态标记      

u8 aRxBuffer[RXBUFFERSIZE];                           //HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler;             //UART句柄

//串口1 通信层初始化

void uart_init(u32 bound)

{    
    //UART 初始化设置
    UART1_Handler.Instance=USART1;                        //USART1
    UART1_Handler.Init.BaudRate=bound;                    //波特率
    UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
    UART1_Handler.Init.StopBits=UART_STOPBITS_1;        //一个停止位
    UART1_Handler.Init.Parity=UART_PARITY_NONE;        //无奇偶校验位
    UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
    UART1_Handler.Init.Mode=UART_MODE_TX_RX;        //收发模式
    HAL_UART_Init(&UART1_Handler);                               //HAL_UART_Init()会使能UART1
    HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);    
}

//串口1 底层初始化,包括时钟使能,引脚配置,中断配置

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef GPIO_Initure;


    if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();            //使能GPIOA时钟
        __HAL_RCC_USART1_CLK_ENABLE();            //使能USART1时钟
        __HAL_RCC_AFIO_CLK_ENABLE();
    
        GPIO_Initure.Pin=GPIO_PIN_9;                              //PA9
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;           //复用推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;   //高速
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                //初始化PA9

        GPIO_Initure.Pin=GPIO_PIN_10;                          //PA10
        GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;    //模式要设置为复用输入模式!    
//        GPIO_Initure.Mode=GPIO_MODE_AF_PP;
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);               //初始化PA10
        
#if EN_USART1_RX
        HAL_NVIC_EnableIRQ(USART1_IRQn);                //使能USART1中断通道
        HAL_NVIC_SetPriority(USART1_IRQn,3,3);           //抢占优先级3,子优先级3
#endif    
    }
}

//串口1 回调函数,用于编写控制逻辑

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART1)                                       //如果是串口1
    {
        if((USART_RX_STA&0x8000)==0)                           //接收未完成
        {
            if(USART_RX_STA&0x4000)                               //接收到了0x0d
            {
                if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;    //接收错误,重新开始
                else USART_RX_STA|=0x8000;                    //接收完成了 
            }
            else                                                                    //还没收到0X0D
            {    
                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;

                                                                                      //接收数据错误,重新开始接收      
                }         
            }
        }
    }
}

//串口1 中断服务程序

void USART1_IRQHandler(void)                    

#if SYSTEM_SUPPORT_OS         //使用OS
    OSIntEnter();    
#endif


    u32 timeout=0;
    HAL_UART_IRQHandler(&UART1_Handler);            //调用HAL库中断处理公用函数
    
    timeout=0;
    while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)
    {
     timeout++;超时处理
     if(timeout>HAL_MAX_DELAY) break;        
    }
     
    timeout=0;
    while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)                                     //一次处理完成之后,重新开启中断并设置RxXferCount为1
    {
     timeout++; //超时处理
     if(timeout>HAL_MAX_DELAY) break;    
    }
#if SYSTEM_SUPPORT_OS         //使用OS
    OSIntExit();                                               
#endif

#endif    

三、main.c 文件

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

int main(void)
{
    u8 len;    
    u16 times=0;
    
    HAL_Init();                             //初始化HAL库    
    Stm32_Clock_Init(RCC_PLL_MUL9);       //设置时钟,72M
    delay_init(72);                       //初始化延时函数
    uart_init(115200);                  //初始化串口
    LED_Init();                            //初始化LED    

while(1)
    {
       if(USART_RX_STA&0x8000)
        {                       
            len=USART_RX_STA&0x3fff;                        //得到此次接收到的数据长度
            printf("\r\n您发送的消息为:\r\n");
            HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);  

                                                                                   //发送接收到的数据
            while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);                                                                                         //等待发送结束
            printf("\r\n\r\n");//插入换行
            USART_RX_STA=0;
        }
        else
        {
            times++;
            if(times%5000==0)
            {
                printf("\r\n 串口实验\r\n");
                printf("wait receive\r\n\r\n\r\n");
            }
            if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
            if(times%30==0)
                LED0=!LED0;                                               //闪烁LED,提示系统正在运行.
            delay_ms(10);   
        } 
    }
}

注意:本文是针对串口(USART)通信的程序代码,本文中没有关于LED程序代码,因此如果直接运行编译器会报错。需要在工程中添加LED的头文件和源文件才可以直接运行。在main.c文件中调用了LED的头文件和源文件,主要是为了指示程序正在运行,有关LED的代码在其他文中总结

备注:欢迎各位同学指正,有关串口通信的问题欢迎评论区留言,一起讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1550737.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据库软题1-数据模型+数据库三级模式两级映像

一、数据模型 (一)常见的数据模型 题1-二维表-关系模型 二、三级模式两级映像 (一) 外模式/模式/内模式 <>视图/基本表/文件 题1-三级模式与数据库的三对应 题2-三级模式与数据库的三对应 题3-视图是虚拟表 解析&#xff1a;视图是从一个或几个基本表&#xff08;或视…

ZYNQ中 PL 使用 PS 端晶振实现流水灯

ZYNQ中 PL 使用 PS 端晶振实现流水灯 Create Block Design 点击 Create Block Design, 然后点击 OK: 添加 IP 核 点击 Diagram 中的 号: 在 IP 核的搜索框中输入 ZYNQ, 找到 ZYNQ7 Processing System 的 IP 核,双击之: Viavado 会把 ZYNQ 的 IP 加到我们的 Block Design 中…

企业如何提升知识产权管理效率?

随着企业规模的扩大和创新活动的增加&#xff0c;知识产权管理日益复杂。有效的知识产权管理不仅能够保护企业的创新成果&#xff0c;还能为企业带来巨大的商业价值。然而&#xff0c;许多企业在知识产权管理方面面临着效率低下的问题&#xff0c;管理效率的提升成为企业亟需解…

交换机支持的以太网协议大全

在现代网络架构中,以太网协议是基础设施的核心组成部分,而交换机作为以太网网络的关键设备,其支持的协议种类繁多。理解这些协议的功能和应用场景对于网络管理员和工程师而言至关重要,因为这些协议决定了网络的性能、稳定性和安全性。 以太网协议的发展经历了从最初的10Mb…

使用apipost工具导入通过swag生成的golang接口文档步骤

1.通过swag init 生成docs接口文档 见使用swag init --parseDependency生成api文档报错解决办法 2.导入操作 ok,操作完成

NB_IOT类产品的通信功能生产测试方案

01 物联网行业中存在的问题 在产品的生产流程中&#xff0c;NB 产品的 Socket 通信测试是一个至关重要的环节。Socket 通信作为一种常用的网络通信方式&#xff0c;对于 NB 产品的性能和稳定性有着直接的影响。 在这个阶段&#xff0c;测试人员会精心设计一系列的测试用例&a…

基于OpenCV的实时年龄与性别识别(支持CPU和GPU)

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

NineData云原生智能数据管理平台新功能发布|2024年9月版

本月发布 3 项更新&#xff0c;其中重点发布 3 项。 重点发布 数据复制 - 新增 Oracle 到 Kafka 复制链路 数据复制功能新增支持将 Oracle 中的数据复制到 Kafka&#xff0c;实现数据的实时流转和分发&#xff0c;支持全量和增量。 数据复制 - 新增库表分组复制 创建复制任务…

网上很好看的动态音频效果是怎么做的?只需两个步骤实现动态音乐效果!

网上很好看的动态音频效果是怎么做的&#xff1f;只需两个步骤实现动态音乐效果&#xff01;大家听音乐的时候&#xff0c;有没看到别人桌面上会有一些音频效果&#xff0c;随着音乐的节奏而跳动。 其实这是用了一些桌面插件&#xff0c;来显示音频效果&#xff0c;咱们这期就…

【小程序】微信小程序课程 -4 项目实战

目录 1、 效果图 2、创建项目 2.1 创建小程序端 2.1.1 先创建纯净项目 2.1.2 删除components 2.1.4 删除app.json红色部分 2.1.5 删除index.json红色部分 2.1.6 删除index.wxss全部内容 2.1.7 删除index.wxml全部内容 2.1.8 app.json创建4个页面 2.1.9 app.json添加…

学习大模型新人必看,大语言模型(LLM)入门学习路线图

Github项目上有一个大语言模型学习路线笔记&#xff0c;它全面涵盖了大语言模型的所需的基础知识学习&#xff0c;LLM前沿算法和架构&#xff0c;以及如何将大语言模型进行工程化实践。这份资料是初学者或有一定基础的开发/算法人员入门活深入大型语言模型学习的优秀参考。这份…

淘宝api上货软件)一刻工具箱,一天上几万不出现爬虫违规,更新开放类目错放功能,淘宝电商必备软件!

天猫淘宝抖音上货神器&#xff0c;助力电商快速铺货 在当今这个信息爆炸、电商飞速发展的时代&#xff0c;如何快速有效地将产品铺货到各大电商平台&#xff0c;成为每一位电商从业者都需要面对的问题。 通过电商API接口能为电商从业者打造的综合辅助工具&#xff0c;支持天猫、…

E34.【C语言】位段练习题

1.题目 分析下列代码中位段在内存中的排布(已知测试平台为VS2022) struct S {int a : 2;int b : 5;int c : 10;int d : 30; };int main() {struct S s { 0 };return 0; } 有关位段的知识点见64.【C语言】再议结构体(下)文 2.提示 VS满足:由低地址向高地址存储,按浪费空间…

基于大数据技术的宠物商品信息比价及推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

谷歌自曝TPU秘密武器,AlphaChip登Nature!深度解读AI设计芯片的发展历程

2020 年&#xff0c;谷歌发表了一篇具有里程碑意义的预印本论文「Chip Placement with Deep Reinforcement Learning」&#xff0c;首次向世界展示了其采用新型强化学习方法设计的芯片布局。这一创新使得谷歌能够在 TPU 的芯片设计中引入 AI&#xff0c;实现了超越人类设计师的…

node的版本管理工具volta

安装方式 # mac curl https://get.volta.sh | bash # Windows Installation winget install Volta.Volta切换版本 volta install node指定版本根据项目固定node和包管理器版本和 该命令会在package.json生成volta的配置&#xff0c;volta会自动读取项目的该配置来决定node的…

Linux环境下的JDK安装详解

JDK安装 在 一些操作系统上&#xff0c;有时会自带 JDK&#xff08;一般都是自己卸载再重新装一个&#xff09;。您可以通过以下命令检查&#xff1a; ##看看是否有自带的jdk java -version rpm -qa | grep -i java如果已经安装了 JDK&#xff0c;可以卸载后再重新安装。 r…

Parallels Desktop19官方中文版10月最新

如何使用 Parallels Desktop 在 Mac 上运行虚拟机 Parallels Desktop 是一款强大的虚拟机软件&#xff0c;允许 Mac 用户在 macOS 上方便地运行 Windows 和其他操作系统。这款软件尤其适合开发者、设计师以及任何需要使用不同操作系统的用户。本文将为新手用户提供一步一步的指…

Devicenet从站数据 转profinet IO项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 网关用DEVICENET协议采集数据 3 5 用PROFINET IO协议转发数据 4 6 案例总结 7 1 案例说明 设置网关采集Devicenet从站设备数据把采集的数据转成profinet IO协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协…