通过串口实现printf函数,中断实现串口数据接收

stm32的工程可以直接使用C标准库函数,其中printf函数没有完全实现,预留了一个后门fputc函数,可以通过实现fputc往串口打印从而实现printf的功能。

 1.fputc格式:

int fputc(int ch,FILE *F)

{     //...... }

//stm32开发板上运行程序,如果主机运行了调试器,程序就会使用主机的输入输出设备//这是方式叫半主机模式,printf如果要通过串口打印,必须关闭半主机模式

#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) 
{     //发送     
      USART_SendData(USART1,ch

); 

   

 //等待上一个数据发送完成

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);        return ch; }

———————————————————————————————————————————

2.使用中断实现串口的接收

    由于串口何时发送数据由CPU决定,不存在无效等待的问题,可以不使用中断,但是串口的接收不由CPU决定何时接收,如果还使用轮询就会存在大量无效等待,此时要使用中断提供效率。

    串口中断和定时器中断类似,需要配置中断开关和NVIC。

NVIC_Init(...);//初始化函数

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断

    在串口中断处理函数中完成数据的接收

void USART1_IRQHandler(void) {    

 //判断是否为接收中断 ---------- USART_GetITStatus(USART1, USART_IT_RXNE);  

   //接收数据 ------------------- data = USART_ReceiveData(USART1);   

  //清除中断标志 --------------- USART_ClearITPendingBit(USART1, USART_IT_RXNE);

}

练习:

    为串口中断实现数据接收和控制命令控制蜂鸣器主要功能函数

#include <stm32f4xx.h>
#include <usart.h>
#include <stdio.h>
#include <string.h>
#include <includes.h>

//stm32开发板上运行程序,如果主机运行了调试器,程序就会使用主机的输入输出设备
//这是方式叫半主机模式,printf如果要通过串口打印,必须关闭半主机模式
#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(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
    //发送
    USART_SendData(USART1,ch);
    
	return ch;
}

void usart1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	//1.开启GPIOA和USART1时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

	//2.配置PA9 PA10为串口功能
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//复用模式
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	
	//3.初始化串口  8N1
	USART_InitStruct.USART_BaudRate = 115200;//波特率
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;//8位数据位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;//1位停止位
	USART_InitStruct.USART_Parity = USART_Parity_No;//无校验
	USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//发送接收模式
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
	USART_Init(USART1,&USART_InitStruct);
	
	//4.开启串口接收中断(清除中断标志)
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	//5.初始化NVIC
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_Init(&NVIC_InitStruct);
	
	//.使能串口
	USART_Cmd(USART1,ENABLE);
}

//发送一个字符(轮询)
void uart1_putc(char ch)
{
	//等待上一个数据发送完成
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
	
	USART_SendData(USART1,ch);
}

//发送字符串
void uart1_puts(const char *s)
{
	while(*s){
		uart1_putc(*s++);
	}
}

volatile u32 uart_flag = 0;//记录串口是否收到了一个完整的数据 1---完整
volatile u8 uart_buf[64] = {0};//记录串口收到的数据
volatile u32 uart_cnt = 0;//记录串口收到的数据长度

//处理串口命令函数
void parse_cmd(void)
{
	while(1){
		if(uart_flag){
			//BEEP命令
			if(strstr((char *)uart_buf,"beep")){
				if(strstr((char *)uart_buf,"on")){
					BEEP = 1;
					printf("beep on!\r\n");
				}
				
				if(strstr((char *)uart_buf,"off")){
					BEEP = 0;
					printf("beep off!\r\n");
				}
			}
			else{//非法命令
				printf("unknow command = %s\r\n",(char *)uart_buf);
			}
			
			//处理完成标志清0,缓冲区清空,个数清0
			uart_flag = 0;
			memset((char *)uart_buf,0,sizeof(uart_buf));
			uart_cnt = 0;
		}
	}
}

//串口1中断处理函数
void USART1_IRQHandler(void)
{
	//u8 data;
	
    if(USART_GetITStatus(USART1, USART_IT_RXNE)==SET){
		//接收串口数据
		uart_buf[uart_cnt++] = USART_ReceiveData(USART1);
		
		//判断数据是否接收完成 ------ 以*结束
		if(uart_buf[uart_cnt-1]=='*'||uart_cnt>=sizeof(uart_buf)){
			uart_flag = 1;
		}
		
		//原路发回
		//uart1_putc(data);
		
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值