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

目录

配置串口引脚

引脚图

中断优先级分组

使能时钟

配置中断优先级

配置串口

重写中断服务函数

清空中断标志位

获取中断标志位

接收函数

打印数据

例程

例程说明

main.h

main.c

usart.h

usart.c

配置串口引脚

引脚图

  1. 配置引脚号

  2. 配置引脚速度

  3. 配置引脚的模式

  4. 引脚初始化

cpp 复制代码
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

中断优先级分组

cpp 复制代码
/*
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);//中断优先级分组

使能时钟

cpp 复制代码
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. 接收中断使能

cpp 复制代码
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. 串口使能

cpp 复制代码
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);//串口使能

重写中断服务函数

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

cpp 复制代码
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);
    }
}

清空中断标志位

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

cpp 复制代码
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

USART_ClearITPendingBit(USART1,USART_IT_RXNE);

获取中断标志位

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

USART_GetITStatus(USART1, USART_IT_RXNE);

接收函数

cpp 复制代码
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

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

打印数据

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

cpp 复制代码
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和蜂鸣器,控制协议自定,比如:

0x01 Led1亮
0x02 Led1灭
0x08 Led2亮
0x09 Led2灭
0x15 蜂鸣器响
0x16 蜂鸣器不响

main.h

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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);
}
相关推荐
is081514 分钟前
在STM32 FreeRTOS环境中使用mutex和ringbuffer实现多任务的UART同步通信
stm32·单片机·嵌入式硬件
景彡先生16 分钟前
STM32中I2C协议详解
stm32·单片机·嵌入式硬件
小庞在加油23 分钟前
《重构项目》基于Apollo架构设计的项目重构方案(多种地图、多阶段、多任务、状态机管理)
c++·重构·apollo架构
让我们一起加油好吗1 小时前
【基础算法】贪心 (四) :区间问题
c++·算法·贪心算法·洛谷
双叶8362 小时前
(C++)任务管理系统(正式版)(迭代器)(list列表基础教程)(STL基础知识)
c语言·开发语言·数据结构·c++·list
星卯教育tony2 小时前
米思齐2.0 3.0 mixly arduino 编程软件下载安装及详情使用指南 导入库文件方法 支持8266 esp32
单片机·嵌入式硬件
七七七七072 小时前
类与对象【下篇】-- 关于类的其它语法
c语言·开发语言·c++
削好皮的Pineapple!2 小时前
C语言模块化编程思维以及直流电机控制(第四天)
c语言·开发语言·单片机
黄皮の电气鼠2 小时前
C++:继承
开发语言·c++·算法
shylyly_2 小时前
专题一_双指针_查找总价格为目标值的两个商品
c++·算法·leetcode·双指针·查找总价格为目标值的两个商品·和为s的两个数