当前位置: 首页 > article >正文

【STM32F103ZET6——库函数】4.串口通讯

目录

配置串口引脚

引脚图

中断优先级分组

使能时钟

配置中断优先级

配置串口

重写中断服务函数

清空中断标志位

获取中断标志位

接收函数

打印数据

例程

例程说明

main.h

main.c

usart.h

usart.c

配置串口引脚

引脚图

  1. 配置引脚号

  2. 配置引脚速度

  3. 配置引脚的模式

  4. 引脚初始化  

GPIO_InitTypeDef GPIO;

//USART1_TX   GPIOA.9
GPIO.GPIO_Pin = GPIO_Pin_9; //PA9
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
GPIO_Init(GPIOA, &GPIO);//初始化GPIOA9

//USART1_RX	  GPIOA.10初始化
GPIO.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO);//初始化GPIOA.10

中断优先级分组

/*
zu_bie:
	NVIC_PriorityGroup_0
	NVIC_PriorityGroup_1
	NVIC_PriorityGroup_2
	NVIC_PriorityGroup_3
	NVIC_PriorityGroup_4
*/
void NVIC_PriorityGroupConfig(zu_bie);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组

使能时钟

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟

配置中断优先级

  1. 配置中断的串口

  2. 配置抢占优先级

  3. 配置子优先级

  4. 通道使能

  5. 接收中断使能

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);//接收中断使能

NVIC_InitTypeDef ZhongDuan;
//Usart1 NVIC 配置
ZhongDuan.NVIC_IRQChannel = USART1_IRQn;
ZhongDuan.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级1
ZhongDuan.NVIC_IRQChannelSubPriority = 1;		//子优先级1
ZhongDuan.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
NVIC_Init(&ZhongDuan);	//根据指定的参数初始化VIC寄存器
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//接收中断使能

配置串口

  1. 配置波特率

  2. 配置数据模式

  3. 配置停止位

  4. 配置奇偶校验位

  5. 配置硬件流传输

  6. 配置收发模式

  7. 串口初始化

  8. 串口使能

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);//串口使能

USART_InitTypeDef ChuanKou;
//USART 初始化设置
ChuanKou.USART_BaudRate = bound;//串口波特率
ChuanKou.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
ChuanKou.USART_StopBits = USART_StopBits_1;//一个停止位
ChuanKou.USART_Parity = USART_Parity_No;//无奇偶校验位
ChuanKou.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
ChuanKou.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
USART_Init(USART1,&ChuanKou);//串口初始化
USART_Cmd(USART1,ENABLE);//串口使能

重写中断服务函数

        注意:中断服务函数的函数已经固定,重新定义相同名字的函数即可,在定义好的函数里写中断的操作,哪个串口发生中断就得重定义哪个串口中断的函数

void USART1_IRQHandler();

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
    u8 JiaoYan_Wei=0;
    u8 j;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        Res =USART_ReceiveData(USART1);	//读取接收到的数据
        data[flag_1]=Res;
        flag_1++;
        if(flag_1==6) {
            flag_1=0;
            flag=1;
        }
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    }
}

清空中断标志位

在中断服务函数里进行操作。

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

USART_ClearITPendingBit(USART1,USART_IT_RXNE);

获取中断标志位

/*
不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断
*/
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);

USART_GetITStatus(USART1, USART_IT_RXNE);

接收函数

uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

Res =USART_ReceiveData(USART1);	//读取接收到的数据

打印数据

注意:得加上下面函数,才能像C语言那样打印到终端,在这里是打印到串口调试助手上

int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (uint8_t) ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return (ch);
}

例程

例程说明

1.编写主程序,初始化串口1,设置波特率为9600,无校验,数据位8位,停止位1位。

2.编写中断服务程序代码实现将接收到的数据保存下来。

3、数据格式为0xaa,0x55,0xxx(有效控制字节), 校验字节(前数相加-1),0x0d,0x0a 。(前两个是头码,后两个是结束码)

4.分析保存的数据,如果数据正确,则将控制单片机进行对应的动作,并把收到的数据发回。

5、.控制动作包括led1、led2和蜂鸣器,控制协议自定,比如:

0x01Led1亮
0x02Led1灭
0x08Led2亮
0x09Led2灭
0x15蜂鸣器响
0x16蜂鸣器不响

main.h

#ifndef _MAIN_H_
#define _MAIN_H_

#include "stm32f10x.h"                  // Device header
#include "stm32f10x_gpio.h"             // Keil::Device:StdPeriph Drivers:GPIO
#include "stm32f10x_tim.h"              // Keil::Device:StdPeriph Drivers:TIM
#include <stm32f10x_rcc.h>
#include <stm32f10x_usart.h>
#include <stm32f10x_sdio.h>
#include <misc.h>
#include <stdio.h>
#include <delay.h>
#include "timch.h"
#include "bsp_SysTick.h"

#include "led.h"
#include "Key.h"
#include "usart.h"
#include "FengMingQi.h"

#endif

main.c

#include "main.h"

extern u8 data[6];
extern u8 flag_1;
extern u8 flag;

int main() {
    u8 key_num;
    u8 FMQ=0;
    u8 j;
    u8 JiaoYan_Wei=0;

    uart_init(9600);

    LED_Init();
    Key_Init();
    FengMingQi_Init();
    while(1) {
        if(flag==1){
			flag=0;	
			printf("\rok\n%x %x %x %x %x %x",data[0],data[1],data[2],data[3],data[4],data[5]);
			JiaoYan_Wei=data[0]+data[1]+data[2]-1;
			if((data[0]==0xaa)&&(data[1]==0x55)&&(JiaoYan_Wei==data[3])&&(data[4]==0x0d)&&(data[5]==0x0a)){
				switch(data[2]) {
					case 0x01: {//aa 55 01 ff 0d 0a
						LED_R_NO();
						break;
					}
					case 0x02: {//aa 55 02 00 0d 0a
						LED_R_OFF();
						break;
					}
					case 0x08: {//aa 55 08 06 0d 0a
						LED_G_NO();
						break;
					}
					case 0x09: {//aa 55 09 07 0d 0a
						LED_G_OFF();
						break;
					}
					case 0x15: {//aa 55 15 13 0d 0a
						FengMingQi_NO();
						break;
					}
					case 0x16: {//aa 55 16 14 0d 0a
						FengMingQi_OFF();
						break;
					}
				}
			}
        }
    }
}

usart.h

#ifndef __USART_H
#define __USART_H

#include "stdio.h"
#include "sys.h"
#include "led.h"
#include "FengMingQi.h"
#include "delay.h"

extern u8 Res;

void uart_init(u32 bound);
void USART1_IRQHandler();

#endif

usart.c

#include "usart.h"

void uart_init(u32 bound) {
    //GPIO端口设置
    GPIO_InitTypeDef GPIO;
    USART_InitTypeDef ChuanKou;
    NVIC_InitTypeDef ZhongDuan;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟

    //USART1_TX   GPIOA.9
    GPIO.GPIO_Pin = GPIO_Pin_9; //PA9
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO);//初始化GPIOA9

    //USART1_RX	  GPIOA.10初始化
    GPIO.GPIO_Pin = GPIO_Pin_10;//PA10
    GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO);//初始化GPIOA.10

    //Usart1 NVIC 配置
    ZhongDuan.NVIC_IRQChannel = USART1_IRQn;
    ZhongDuan.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级1
    ZhongDuan.NVIC_IRQChannelSubPriority = 1;		//子优先级1
    ZhongDuan.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&ZhongDuan);	//根据指定的参数初始化VIC寄存器
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//接收中断使能

    //USART 初始化设置
    ChuanKou.USART_BaudRate = bound;//串口波特率
    ChuanKou.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    ChuanKou.USART_StopBits = USART_StopBits_1;//一个停止位
    ChuanKou.USART_Parity = USART_Parity_No;//无奇偶校验位
    ChuanKou.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    ChuanKou.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART1,&ChuanKou);//串口初始化
    USART_Cmd(USART1,ENABLE);//串口使能
}

u8 data[6];
u8 Res;
u8 flag_1=0;
u8 flag;

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
    u8 JiaoYan_Wei=0;
    u8 j;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        Res =USART_ReceiveData(USART1);	//读取接收到的数据
        data[flag_1]=Res;
        flag_1++;
        if(flag_1==6) {
            flag_1=0;
            flag=1;
        }
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志位
    }
}

int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (uint8_t) ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return (ch);
}

http://www.kler.cn/a/566530.html

相关文章:

  • Web3.py 入门笔记
  • 用大白话解释基础框架Spring Boot——像“装修套餐”一样简单
  • 2025年如何实现安卓、iOS、鸿蒙跨平台开发
  • vscode中使用PlatformIO创建工程加载慢
  • xss自动化扫描工具-DALFox
  • 阿里云的 ECS(Elastic Compute Service)实例
  • CD9.【C++ Dev】对“auto替换为变量实际的类型”的解释
  • AI大模型-提示工程学习笔记18—推理与行动的协同 (ReAct)
  • Go语言学习笔记(四)
  • idea导入新项目pom报错设置
  • PHP面试题--后端部分
  • MyBatis教程
  • 本地部署Deepseek+Cherry Studio
  • sklearn中的决策树-分类树:实例-分类树在合成数据集上的表现
  • 【MySQL】服务正在启动或停止中,请稍候片刻后再试一次【解决方案】
  • 2025中建二测笔试考什么?北森题库考点复习|附精华备考面试攻略
  • TCP/IP 5层协议簇:物理层
  • 重构清洁想象,石头科技首创五轴仿生机械手打破传统清洁边界
  • 自回归与自监督分别是什么,区别是什么
  • MySQL 索引介绍