USART串口驱动SIM800L或者ESP8266

16 篇文章 0 订阅

最近要驱动了SIM800L发现自己用的程序好乱,今天写个死的

#include "USART.h"
#include "stdio.h"
#include "string.h"
#include "delay.h"

/**
*@function:把串口接收到的数据都存在USART_RX_BUF[]中,把它定义成为全局变量以供使用
*						另外,接收完成之后,USART1_RX_STA的第15位还是1的状态,使用完数据记得清零
*						不然无法进行第二次接收
*/


/**用库函数配置优先级,最近喜欢库函数和寄存器两种混着用
	NVIC_InitTypeDef NVIC_InitStructure;
  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寄存器
*/


u8 USART1_RX_BUF[USART1_Receive_Len];//一个字节长度类型的数组
u16 USART1_RX_STA=0;       //接收状态标记	

void GenralUSART_Init(int pclk2,int bound)
{
	float temp;
	u16 mantissa;//存放波特率的整数部分
	u16 fraction;//存放波特率的小数部分
	temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
	mantissa=temp;				 //得到整数部分
	fraction=(temp-mantissa)*16; //得到小数部分	 
  mantissa<<=4;
	mantissa+=fraction; 
	RCC->APB2ENR|=1<<2;   //使能PORTA口时钟  
	RCC->APB2ENR|=1<<14;  //使能串口时钟 
	GPIOA->CRH&=0XFFFFF00F;//IO状态设置PA9PA10
	GPIOA->CRH|=0X000008B0;//IO状态设置 
	RCC->APB2RSTR|=1<<14;   //复位串口1
	RCC->APB2RSTR&=~(1<<14);//停止复位	   	   
	//波特率设置
 	USART1->BRR=mantissa; // 波特率设置	 
	USART1->CR1|=0X200C;  //1位停止,无校验位.

	USART1->CR1|=1<<5;    //接收缓冲区非空中断使能	    	
	MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级 
}
/*通过串口发送一个字符串*/
void SendStrToUSART1(u8* str)
{
	int i,j;
	i=strlen((const char*)str);
	for(j=0;j<i;j++)
	{
		USART1->DR=str[j];
		while(((USART1->SR)&(1<<6))==0);//等待发送完成
	}
}
/*查看USART接收的数据是否含有自己的字符串*/
u8* USART_Check_CMD(u8* str)
{
	char* Rstr=0;
	if(USART1_RX_STA&0x8000)//接受到一个串数据,第15位在接收完成一个以\r\n结尾的字符串后才会被置一
	{
		USART1_RX_BUF[USART1_RX_STA&0X7FFF]=0;//添加结束符,这里没看明白
		Rstr=strstr((const char*)USART1_RX_BUF,(const char*)str);
	}
	return (u8*)Rstr;
}
/**
*@par:cmd:发送的命令
*			ack:期望的响应
*			waittime:超时时间,n*10ms
*@ret:0成功	1失败
*/
u8 USART_Send_CMD(u8* cmd,u8* ack,u16 waittime)
{
	USART1_RX_STA=0;
	SendStrToUSART1(cmd);
	if(waittime&&ack)
	{
		while(--waittime)
		{
			delay_ms(10);
			if(USART1_RX_STA&0x8000)//接受到数据
			{
				if(USART_Check_CMD(ack))
				{
					//接收到对应的响应,跳出while循环
					break;
				}
				//接收到数据后清除状态位
				USART1_RX_STA=0;
			}
			if(waittime==0)return 1;//到时间未得到响应
		}
		
	}
	return 0;
}
/**
*@function:一次中断处理一个字节数据
*@Attention:0x0d:/r  0x0a:/n
*/
void USART1_IRQHandler(void)
{
	u8 res;	
	if(USART1->SR&(1<<5))	//接收寄存器非空
	{	 
		res=USART1->DR;//取出数据寄存器的一个字节的数据 
		if((USART1_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART1_RX_STA&0x4000)//如果接收到/r,那么如果数据没有错误现在接收到的应该是/n
			{
				if(res!=0x0a)USART1_RX_STA=0;//如果接收到的不是/n,那就表示接收错误,重新开始
				else USART1_RX_STA|=0x8000;	//如果是,则表示接收完成了 
			}else //还没收到/r
			{	
				if(res==0x0d)USART1_RX_STA|=1<<14;//标记已经接收到/r,此时随后又执行一次接收数据,即接收/n
				else
				{
					USART1_RX_BUF[USART1_RX_STA&0X3FFF]=res;//USART_RX_STA&0X3FFF表示数据长度
					USART1_RX_STA++;//数据长度+1
					if(USART1_RX_STA>(USART1_Receive_Len-1))USART1_RX_STA=0;//数据长度大于定义的最大接收长度,接收数据错误,重新开始接收	  
				}		 
			}
		}  		 									     
	}
} 
/************************printf()函数*************************************/
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. */ 
}; 
///* FILE is typedef’ d in stdio.h. */ 
FILE __stdout; 

//重定向fputc函数
//printf的输出,指向fputc,由fputc输出到串口
//这里使用串口1(USART1)输出printf信息
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//等待上一次串口数据发送完成  
	USART1->DR = (u8) ch;      	//写DR,串口1将发送数据
	return ch;
}
/************************printf()函数*************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值