【STM32单片机】STM32F103RCT6 串口1 串口2 串口3 串口4 串口5 初始化,标准库 ,支持printf

单片机介绍

STM32F103RCT6是一款主流性能系列的单片机,采用Arm Cortex-M3内核,具有256K字节的Flash存储器,72 MHz的CPU频率,支持电机控制、USB和CAN等功能。

该产品已经批量生产,10kU的单价为4.0035美元,采用LQFP 64封装,尺寸为10x10x1.4mm。

STM32F103xC、STM32F103xD和STM32F103xE性能系列产品采用高性能的ARM Cortex-M3 32位RISC内核,工作频率为72 MHz。它们拥有高速嵌入式存储器(Flash存储器最高达512K字节,SRAM最高达64K字节),以及广泛的增强型I/O口和外围设备,可以连接两个APB总线。所有这些设备都提供了三路12位ADC、四个通用16位定时器和两个PWM定时器,以及标准和高级通信接口:最多两个I2C接口、三个SPI接口、两个I2S接口、一个SDIO接口、五个串行USART接口、一个USB接口和一个CAN接口。

STM32F103xC/D/E高密度性能系列单片机可在-40℃至+105℃的温度范围内工作,电源电压为2.0至3.6V。它们具有一套全面的省电模式,适用于低功耗应用的设计。

这些特性使得STM32F103xC/D/E高密度性能系列单片机非常适合广泛的应用领域,如电机驱动、应用控制、医疗和便携设备、个人电脑和游戏外围设备、GPS平台、工业应用、可编程逻辑控制器(PLC)、变频器、打印机、扫描仪、报警系统、视频对讲系统和暖通空调系统等。

主要特性包括:

72 MHz的最大频率,每MHz可执行1.25 DMIPS(Dhrystone 2.1)指令
单周期乘法和硬件除法
256至512 K字节的Flash存储器
最多64 K字节的SRAM
灵活的静态存储器控制器,支持紧凑型Flash、SRAM、PSRAM、NOR和NAND存储器
LCD并行接口,支持8080和6800模式
2.0至3.6 V的应用供电和I/O口电压
POR(上电复位)、PDR(电源降低复位)和可编程电压检测器(PVD)
4至16 MHz的晶振和内部8 MHz的出厂修裁RC振荡器
带校准的内部40 kHz RC振荡器
带校准的32 kHz时钟用于RTC(实时时钟)
低功耗模式:休眠、停止和待机
VBAT供电用于RTC和备份寄存器
3路12位、1微秒的A/D转换器(最多21个通道),输入范围为0至3.6 V
三路采样和保持功能,温度传感器
2路12位D/A转换器
支持DMA(直接内存访问)的外设包括定时器、ADC、DAC、SDIO、I2S、SPI、I2C和USART
调试模式:串行线调试(SWD)和JTAG接口,Cortex-M3嵌入式追踪宏单元
最多112个快速I/O口,51/80/112个I/O口,可以映射到16个外部中断向量上,几乎所有的I/O都能耐受5V电平
最多11个定时器,包括四路16位定时器,每个定时器可配置为4路输入捕获/输出比较/脉冲宽度调制(PWM)或脉冲计数器及象限(增量)编码器输入;两路带死区生成和紧急停止功能的16位电机控制PWM定时器;两路看门狗定时器(独立和窗口);SysTick定时器,用于倒计时的24位;
最多13个通信接口,包括最多2个I2C接口(支持SMBus/PMBus)、最多5个USART接口(支持ISO 7816接口、LIN、IrDA功能、调制解调器控制)、最多3个SPI接口(18 Mbit/s),其中2个带I2S接口复用,CAN接口(2.0B主动型)、USB 2.0全速接口、SDIO接口
CRC(循环冗余校验)计算单元,96位唯一标识符
ECOPACK®封装形式。

引脚

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

DMA—直接存储器访问

看看资料:
https://doc.embedfire.com/mcu/stm32/f103mini/std/zh/latest/book/DMA.html

DMA控制器包含了DMA1和DMA2,其中DMA1有7个通道,DMA2有5个通道, 这里的通道可以理解为传输数据的一种管道。要注意的是DMA2只存在于大容量产品和互联型产品中。

STM32F103RCT6 是大容量产品。256K。

小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和 STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和 STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控 制器。
互联型产品是指STM32F105xx和STM32F107xx微控制器。

DMA请求映像表:

在这里插入图片描述
在这里插入图片描述
发现没UART5_TX,那这里我的串口就不用DMA来配置了。

串口 引脚

在这里插入图片描述
在这里插入图片描述

串口1,初始化,发送与接收

用的正点原子代码,这个串口1是默认就用的,这里给出代码:

usart.c

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

//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif


//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#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


void uart_init(u32 bound) {
    
    
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

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

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

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

    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器

    //USART 初始化设置

    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_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
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_Cmd(USART1, ENABLE);                    //使能串口1

}

void USART1_IRQHandler(void)                    //串口1中断服务程序
{
    
    
    u8 Res;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
    
    
        Res = USART_ReceiveData(USART1);    //读取接收到的数据
        printf("收到了一个字符: %c\r\n", Res);
    }

}




usart.h

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


//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);

#endif



懒得定义文件,接下来我将串口2、3、4、5的初始化函数的定义写在usart.c、接收中断写在usart.c、初始化函数的声明写在usart.h、调用写在main.c。调用无非就是类似于uart_init(115200)的定义了。接下来的小节里都直接给出定义来。

在这里插入图片描述

串口2,初始化,发送与接收



//串口2 PA2 PA3 ,APB1时钟
void uart2_init(u32 bound){
    
    
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);    //使能USART2,GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //使能USART2,GPIOA时钟

    //USART2_TX   GPIOA.2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2

    //USART2_RX	  GPIOA.3初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3

    //Usart2 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_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(USART2, &USART_InitStructure); //初始化串口2
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_Cmd(USART2, ENABLE);                    //使能串口2
}

void u2_printf(char* fmt, ...)
{
    
    
	  int i;
	  int len;
    char buffer[50]; //足够容纳才可以,可以搞大点
    va_list args;
    va_start(args, fmt);
    vsprintf(buffer, fmt, args);
    va_end(args);

    len = strlen(buffer);

    for( i=0; i<len; i++)
    {
    
    
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); //等待发送完毕
        USART_SendData(USART2, buffer[i]); //发送一个字符
    }
}

void USART2_IRQHandler(void)                    //串口2中断服务程序
{
    
    
    u8 Res;
    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
    
    
        Res = USART_ReceiveData(USART2);    //读取接收到的数据
			
        u2_printf("收到了一个字符: %c\r\n", Res);
    }

}


串口3,初始化,发送与接收


//串口3 PB10 PB11 ,APB1时钟
void uart3_init(u32 bound) {
    
    
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);    //使能USART3,GPIOB时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //使能USART3,GPIOB时钟

    //USART3_TX   GPIOB.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10

    //USART3_RX	  GPIOB.11初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11

    //Usart3 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_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(USART3, &USART_InitStructure); //初始化串口3
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_Cmd(USART3, ENABLE);                    //使能串口3
}

void u3_printf(char *fmt, ...) {
    
    
    int i;
    int len;
    char buffer[50]; //足够容纳才可以,可以搞大点
    va_list args;
    va_start(args, fmt);
    vsprintf(buffer, fmt, args);
    va_end(args);

    len = strlen(buffer);

    for (i = 0; i < len; i++) {
    
    
        while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); //等待发送完毕
        USART_SendData(USART3, buffer[i]); //发送一个字符
    }
}

void USART3_IRQHandler(void)                    //串口3中断服务程序
{
    
    
    u8 Res;
    if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
    
    
        Res = USART_ReceiveData(USART3);    //读取接收到的数据

        u3_printf("收到了一个字符: %c\r\n", Res);
    }

}

串口4,初始化,发送与接收


//串口4 PC10 PC11 ,APB1时钟
void uart4_init(u32 bound) {
    
    
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);    //使能UART4,GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);    //使能UART4,GPIOC时钟

    //UART4_TX   GPIOC.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10

    //UART4_RX	  GPIOC.11初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PC11
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.11

    //Usart4 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_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(UART4, &USART_InitStructure); //初始化串口4
    USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_Cmd(UART4, ENABLE);                    //使能串口4
}

void u4_printf(char *fmt, ...) {
    
    
    int i;
    int len;
    char buffer[50]; //足够容纳才可以,可以搞大点
    va_list args;
    va_start(args, fmt);
    vsprintf(buffer, fmt, args);
    va_end(args);

    len = strlen(buffer);

    for (i = 0; i < len; i++) {
    
    
        while (USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET); //等待发送完毕
        USART_SendData(UART4, buffer[i]); //发送一个字符
    }
}

void UART4_IRQHandler(void)                    //串口4中断服务程序
{
    
    
    u8 Res;
    if (USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
    
    
        Res = USART_ReceiveData(UART4);    //读取接收到的数据

        u4_printf("收到了一个字符: %c\r\n", Res);
    }

}

串口5,初始化,发送与接收


//串口5 PC12 PD2 ,APB1时钟
void uart5_init(u32 bound) {
    
    
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);    //使能UART5,GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);    //使能UART5,GPIOC时钟

    //UART5_TX   GPIOD.12
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PD.12
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
    GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD.12

    //UART5_RX	  GPIOD.2初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PD2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD.2

    //Usart5 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_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(UART5, &USART_InitStructure); //初始化串口5
    USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_Cmd(UART5, ENABLE);                    //使能串口5
}

void u5_printf(char *fmt, ...) {
    
    
    int i;
    int len;
    char buffer[50]; //足够容纳才可以,可以搞大点
    va_list args;
    va_start(args, fmt);
    vsprintf(buffer, fmt, args);
    va_end(args);

    len = strlen(buffer);

    for (i = 0; i < len; i++) {
    
    
        while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET); //等待发送完毕
        USART_SendData(UART5, buffer[i]); //发送一个字符
    }
}

void UART5_IRQHandler(void)                    //串口5中断服务程序
{
    
    
    u8 Res;
    if (USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
    
    
        Res = USART_ReceiveData(UART5);    //读取接收到的数据

        u5_printf("收到了一个字符: %c\r\n", Res);
    }

}

猜你喜欢

转载自blog.csdn.net/x1131230123/article/details/132612923