stm32学习之串口的使用

文章内容仅个人的理解,如有错误还请各位多多包涵

参考:b站:海创电子工作室

硬件

单片机:stm32f103c8t6

一、带大家了解这款单片机串口所在的引脚

一共有三个串口

二、使用方法

2.1原理

看不懂是吧,没关系,知道用就行

这是初始化串口配置

代码,以串口1举例

/* 串口1初始化 */
void USART1_init(void)
{
		GPIO_InitTypeDef GPIO_InitStructure;//gpio口配置
	  USART_InitTypeDef USART_InitStructure;//串口配置
	  NVIC_InitTypeDef NVIC_InitStructure;//中断配置
	
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	
		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
	
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 
		
		USART_InitStructure.USART_BaudRate = 115200;//串口波特率
		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
		
		
		
		//Usart1 NVIC 配置
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
		
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级3
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
		NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
		
	
		
		USART_Cmd(USART1, ENABLE);   //打开串口

}
                                        //接收中断函数
	/* 中断1 */
  
void USART1_IRQHandler(void)                						//USART中断函数
{	
    //写自己需要执行的操作,这里是串口1接收到的数据存在data1里,在用串口2发送
 	u16 Data1;
    while(USART_GetITStatus(USART1, USART_IT_RXNE) == RESET);           //如果USART1接收
	Data1 =USART_ReceiveData(USART1);					//将USART1接收到的数据赋值给
    USART_SendData(USART2,Data1);	
    USART_ClearITPendingBit(USART1,USART_IT_RXNE);        //清除USART1的接收中断标志位

} 	
//知道加上就好,不用看懂

/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */

#if 1
#if (__ARMCC_VERSION >= 6010050)                    /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");          /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");            /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */

#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)

struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};

#endif

/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */

看不懂中断函数看这里

三、ussrt.h与usart.c

#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"                  
#include "delay.h"
#include "stdio.h" 
#include "string.h" 
#include <stdarg.h>
#include "wifi.h"                  // Device header
#include "OLED.h" /*这里使用的是串口1(a9,a10)
	串口2(a2,a3)
	串口3(b10,b11)
*/
/*    一、流程
1确定1-3串口
	1.2打开串口时钟以及所对应引脚时钟
	1.3初始化引脚和串口
	1.4打开串口
2串口中断(*使用中断要保证程序一直再运行)
	2.1配置串口中断
	2.2打开中断
3.打开串口
			二、可以使用printf打印()使用的是串口1
					u2_printf(使用的是串口2)
*/

void USART1_init(void);//初始化
void USART2_init(void);//初始化
void USART_SendByte(USART_TypeDef* USARTx,uint16_t Data);
void USART_SendString(USART_TypeDef* USARTx, char *str);//发送字符串
uint8_t USART_ReceiyeByte(USART_TypeDef* USARTx);
void u2_printf(char* fmt, ...);

#endif

usart.c

#include "usart.h"    
/*

*/
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */

#if 1
#if (__ARMCC_VERSION >= 6010050)                    /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");          /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");            /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */

#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)

struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};

#endif

/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
    ch = ch;
    return ch;
}

/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}

char *_sys_command_string(char *cmd, int len)
{
    return NULL;
}

/* FILE 在 stdio.h里面定义. */
FILE __stdout;

/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 ,用到串口一
其中串口可根据实际使用情况调整 */
int fputc(int ch, FILE *f)
{
    while ((USART1->SR & 0X40) == 0);             /* 等待上一个字符发送完成 */

    USART1->DR = (uint8_t)ch;                     /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}

#endif
/***********************************************END*******************************************/

/* 打印配置用的是串口2,得初始化串口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]); //发送一个字符
    }
}



/* 串口1初始化 */
void USART1_init(void)
{
		GPIO_InitTypeDef GPIO_InitStructure;
	  USART_InitTypeDef USART_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructure;
	
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	
		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
	
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 
		
		USART_InitStructure.USART_BaudRate = 115200;//串口波特率
		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
		
		
		
		//Usart1 NVIC 配置
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
		
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级3
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
		NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
		
	
		
		USART_Cmd(USART1, ENABLE);   //打开串口
}



		
/* 串口2初始化 */
void USART2_init(void)
{
		//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 = 115200;//串口波特率
    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 USART_SendByte(USART_TypeDef *USARTx,uint16_t Data)
	{
		
		assert_param(IS_USART_ALL_PERIPH(USARTx));
		assert_param(IS_USART_DATA(Data));
		USARTx->DR=(Data&(uint16_t)0x01FF);
		while (USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
	}
		
void USART_SendString(USART_TypeDef* USARTx, char *str) 
	{  
		while(*str != '\0') 
			{  
				USART_SendByte(USARTx, *str++);  
			}  
			
	  
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);   

	}
	
	/* 接受 */
uint8_t USART_ReceiyeByte(USART_TypeDef *USARTx)
	{
		
		while(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE)==RESET);
		return (uint8_t)USART_ReceiveData(USARTx);
	}

	/* 中断1 */
  
void USART1_IRQHandler(void)                						//USART中断函数
{		 
 	  u16 Data1;
	  while(USART_GetITStatus(USART1, USART_IT_RXNE) == RESET);           //如果USART1接收中断SET
		Data1 =USART_ReceiveData(USART1);					//将USART1接收到的数据赋值给Data
		USART_SendData(USART2,Data1);						//用串口2将Data的值发送出去		
//--------------------------
	judge_receive_end();

//-----------------	
		
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);        //清除USART1的接收中断标志位

} 	

void USART2_IRQHandler(void)                    //串口2中断服务程序
{
    u16 Data2;
	  while(USART_GetITStatus(USART2, USART_IT_RXNE) == RESET);           //如果USART1接收中断SET
		Data2 =USART_ReceiveData(USART2);					//将USART接收到的数据赋值给Data
		USART_SendData(USART2,Data2);						//将Data的值发送出去
		
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);        //清除USART1的接收中断标志位

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值