• USART串口驱动SIM800L或者ESP8266


    最近要驱动了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位在接收完成一个以
    结尾的字符串后才会被置一
    	{
    		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()函数*************************************/
    
    
    
  • 相关阅读:
    linux 下内存检查工具 valgrind 及 sanitizer 编译选项及静态检查工具
    jQuery中 inArray
    CLEAN crxMouse Gestures 插件被标记为不安全
    如何理解DMZ?
    如何完整备份浏览器数据(Chrome、Firefox)
    Windows 分屏工具
    JS监听H5返回
    华为账号安全性怎么样?
    IOS Safari keyup不生效如何解决?
    如何下载JD图片 不带logo图片?
  • 原文地址:https://www.cnblogs.com/hhsxy/p/14018412.html
Copyright © 2020-2023  润新知