open串口s8端程序

思路,用stc8a的P10,P11串口二,串口2的波特率用的是定时器2产生,9600,定时器1作为串口监视器,监事接收的信息。
大概隔300ms监视一次,注意。
然后提取串口的缓冲的信息。进行处理,判断等等
stc端的程序

#include "stc8a8k.h"
#include "delay.h"
#include "oled.h"
#include "stdio.h"   //sprintf函数
#include "usart2.h"  //串口2是P10_RXD2  .P11_TXD2管脚

//*************************串口变量,和UART2.C一致,不能改***************************
bit flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0;    //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0;   //接收字节计数器
unsigned char pdata bufRxd[64];  //接收字节缓冲区
//*************************************************************************

//************************************************不能删除

//因为其他单片机传来的数据存在小数浮点数,所以这里设置一个共用体,方便一个个字节接收之后,
//转换成浮点数。

//共用体
// union 共用体名{
//     成员列表
// };
union f_data
{
	float fdata;
	unsigned char cdata[4];
}; 
//单精度的浮点数,一个浮点数,是四个字节,两个同一个内存空间放数据,便于拆分字节

union f_data floatdata0;        //定义一个变量,放在这个空间,这个是全局变量
//*************************************************************


//************************************************不能删除

//因为其他单片机传来的数据存在整型,所以这里设置一个共用体,方便一个个字节接收之后,
//转换成整型。

//共用体
// union 共用体名{
//     成员列表
// };
union int_data
{
	int intdata;
	unsigned char cdata[2];
}; 
//整型,是2个字节,两个同一个内存空间放数据,便于拆分字节
//举例定义一个int变量,后面可以参照这个定义

//union int_data int0        //定义一个变量,放在这个空间,这个是全局变量**************

//*************************************************************
//传递的数据格式————————————————————————————
//帧头+功能码
//    +浮点数0字节1+浮点数0字节2+浮点数0字节3+浮点数0字节4
//    +浮点数1字节1+浮点数1字节2+浮点数1字节3+浮点数1字节4
//    +整型数0字节1+整型数0字节2
//    +整型数1字节1+整型数1字节2
//    +字符型1字节1
//    +字符型2字节1
//+帧尾
//+校验和(这里暂时不用校验和)

//举例说明:
//openmv摄像头,检测到某个东西的中心坐标为3.15,4.56,直径为12,颜色为红色(代号200),发送字符10,字符s
//总共是
//帧头+功能码+3.15+4.56+12+200+10+‘s’+帧尾
//由于浮点数占据四个字节,在网上http://lostphp.com/hexconvert/,IEEE 754浮点数十六进制相互转换(32位,四字节,单精度)
//十位数,输入3.15,得到对应的四字节为40 49 99 99(就是0x40+0x49+0x99+0x99)四个字节,
//输入4.56,得到对应四个字节40 91 EB 85,就是(0x40+0x91+0xeb+0x85)四个字节
//所以发送的字节为:
//帧头+功能码+(0x40+0x49+0x99+0x99)+(0x40+0x91+0xEB+0x85)+(0x00+0x0c)+(0x00+0xC8)+0x0a+'s'(对应ascii码)+帧尾
//上述的括号,是意思是说,这是一个数据,只不过是一个个字节发过来。不发送括号
//***********注意:包括帧头,帧尾,总共是17个字节;
//帧尾是16号,从0计算,0-16共17个字节

//现在51需要利用串口接收上面的数据,然后放到对应的变量中,显示出来,并且用来指导后面的其他动作,
//比如让机械手跑到3.15,4.56这个坐标等等。

//将串口接收的数据,放到对应变量里面:如果数据格式,变量等发生变化,也要对应的进行变化
//比如多了一个浮点型,也是按照上面分析的一样,定义多一个变量,后面就能使用了。

#define FrameLen 17   //一共17个字节
unsigned char  StartChar=0xab;  //帧头定义为0xab
//功能码  0x01----接收的是信息1:任务二维码;123+321
//0x02,接收的是信息2:颜色信息
//0x03, 接收的是信息3:xxxx
//0x04: 接收的是信息4:xxx...可以根据实际情况,继续添加不同的作用
//接收缓冲区的信息;
unsigned char FunCode=0x00;//功能码 
#define Fun1 0x31
#define Fun2 0x32
#define Fun3 0x33
#define Fun4 0xd1 //openmv发送过来的二维码确认代码0xd1=209

unsigned char Message1[16]={0x00};//存放任务二维码:123+321

union f_data xzuobiao; 
union f_data yzuobiao; 
union int_data zhijing;
union int_data yanse;
unsigned char char0;
unsigned char char1;
unsigned char  EndChar1=0xba;//帧尾定义为0xba(坐标的帧尾)
unsigned char  EndChar2=0xba;//帧尾定义为0xba(任务二维码的帧尾)
unsigned char  CheckSumNum=0x00;//校验和,这里不用到校验和,后面添加

unsigned char flagCode=0;
//*************************************************************************
void UartAction(unsigned char *buf, unsigned char len);//串口接收到数据后,执行对应的命令
void ConfigTimer0();//定时器0配置,1ms定时时间
//所以需要ascii码,实际计算是利用数值进行计算的;

unsigned char  intchar[2]={0x00,0x00};//给hex--char用
//******************************************************************
//******************************************************************
void portmode();
unsigned long Str_Long(char *str,unsigned char len) ;
//******************************************************************
//******************************************************************


//**************************************************************************
void main()
{
	unsigned char ix=0;
	floatdata0.fdata=3.15;//这个union里面的fdata
	portmode();
  ConfigTimer0();
	OLED_Init();
	UART2_init();
	OLED_ShowString(0,1,"bbb");
	IE2  =0x01;	    	  // 开串口2中断
	EA   = 1;		      // 开总中断
	delay_tms(5000);
	
	//延时10s,之后开始发送,检测二维码的数据,直到得到串口发来的数据
	
	
	flagCode=1;
	//直到接收到openmv模块发来的确认信息,否则不断发送
	//确认信息:0xab+0xd1+0xba+校验码
	
// 	
	while(flagCode)//flagCode=0是在等待上位机发过来指令
	{
			UART_Send_Byte(0xab);
		  delay_tms(2);
	    UART_Send_Byte(0x11);
		  delay_tms(2);
			UART_Send_Byte(0xba);//(0xab+0x11+0xba)%256
		  delay_tms(2);
 			UART_Send_Byte((0xab+0x11+0xba)%256);//发送校验码
		  delay_tms(2);
		 // OLED_ShowString(100,4,"998");
		  delay_tms(100);
		
		  UartDriver();//读取串口数据,并且执行串口执行函数;
		  
		
	}
	// OLED_ShowString(0,3,"OKOKOK");
	delay_tms(100);
	
	while(1)
	{    
		 //  OLED_ShowString(100,5,"XXX"); //		OLED_ShowString(10,3,"Fun4OK"); 
			 UartDriver();//读取串口数据,并且执行串口执行函数;
		}
		  OLED_ShowString(100,4,"oouX");

}


//****************************端口模式设置,准双向口
void portmode()
{
	P0M1=0x00;P0M0=0x00;
	P1M1=0x00;P1M0=0x00;
	P2M1=0x00;P2M0=0x00;
	P3M1=0x00;P3M0=0x00;
	P4M1=0x00;P4M0=0x00;
	P5M1=0x00;P5M0=0x00;
	P6M1=0x00;P6M0=0x00;
	P7M1=0x00;P7M0=0x00;
}
/*********************串口动作函数,根据接收到的命令帧执行响应的动作
   buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction(unsigned char *buf, unsigned char len)
{
	unsigned char disbuf[9];//用于OLED显示浮点数开辟的缓冲区
	long temp0=0;
	//帧头肯定对,因为在接收函数里面,如果帧头不对,是不接受数据的,
	//void Uart2Isr() interrupt 8 using 1 里面,不然进入不了这个函数
   //将接收的数据,放到对应的变量里面;
	//判断一下帧尾,看是不是发送完数据
	//判别第二个功能码,从而知道传来的是什么信息。
	
	FunCode=*(buf+1);
	switch(FunCode)
	{
		//*********************************************************
		case 0x31:  //0x01任务二维码:123+321,第一次搬运+第二次搬运
// 		   OLED_ShowChar(0,5,FunCode);
// 	     OLED_ShowNum(15,2,FunCode,3,12);//209  ac
	   	 OLED_ShowChar(30,5,'k');
		
				Message1[0]=*(buf+2) ;
				Message1[1]=*(buf+3) ;
				Message1[2]=*(buf+4) ;
				Message1[3]=*(buf+5) ;
				Message1[4]=*(buf+6) ;
				Message1[5]=*(buf+7) ;
				Message1[6]=*(buf+8) ;

// //openmv中发来的直接包括了+0x30,就是char类型
       OLED_ShowChar(0,4,      Message1[0]);
			 OLED_ShowChar(8,4,      Message1[1]);
		   OLED_ShowChar(16,4,     Message1[2]);
			 OLED_ShowChar(24,4,     Message1[3]);
		   OLED_ShowChar(32,4,     Message1[4]);			 
			 OLED_ShowChar(40,4,     Message1[5]);
		   OLED_ShowChar(48,4,     Message1[6]);
			 
		    break;
		
// 		//判断有没有帧尾;
// 		if(EndChar1==*(buf+10))//帧尾是不是相等,数据有没有发送完成
// 		//**************************功能1:任务码
// 			{
// 				Message1[0]=*(buf+2) ;
// 				Message1[1]=*(buf+3) ;
// 				Message1[2]=*(buf+4) ;
// 				Message1[3]=*(buf+5) ;
// 				Message1[4]=*(buf+6) ;
// 				Message1[5]=*(buf+7) ;
// 				Message1[6]=*(buf+8) ;
// 				//第九个是空格,字符串发送的话,会多一个空格
// 				//第十个是帧尾
// 				
// 			}
		//  break;
		//*********************************************************
		case Fun2:  //颜色信息
			Message1[0]=*(buf+2) ;
		  break;
		//*********************************************************
		case Fun3:
			//判断有没有帧尾,是不是完整的命令,这里的15,是说长度-1
			//帧头:*(buf+0)
			//功能码:*(buf+1)
		
		
			//浮点数0:*(buf+2)   *(buf+3)   *(buf+4) *(buf+5)  
			//浮点数1: *(buf+6)   *(buf+7)   *(buf+8)*(buf+9) 
			//整型0:  *(buf+10) *(buf+11) 
			//整型1:  *(buf+12) *(buf+13) 
			//字符0:  *(buf+14) 
			//字符1:  *(buf+15) 
			//帧尾:  *(buf+16) 	
	
	if(EndChar1==*(buf+(FrameLen-1)))//帧尾是不是相等,数据有没有发送完成
	{
			//PC先来的高字节,放在在51的低位,大端模式和小端模式的区别,百度下
			xzuobiao.cdata[0]=*(buf+1);
			xzuobiao.cdata[1]=*(buf+2);
			xzuobiao.cdata[2]=*(buf+3);
			xzuobiao.cdata[3]=*(buf+4);
		
    //PC先来的高字节,放在在51的低位,大端模式和小端模式的区别,百度下
			yzuobiao.cdata[0]=*(buf+5);
			yzuobiao.cdata[1]=*(buf+6);
			yzuobiao.cdata[2]=*(buf+7);
			yzuobiao.cdata[3]=*(buf+8);
		
		//PC先来的高字节,放在在51的低位,大端模式和小端模式的区别,百度下
      zhijing.cdata[0]=*(buf+9);
	    zhijing.cdata[1]=*(buf+10);
		
		//PC先来的高字节,放在在51的低位,大端模式和小端模式的区别,百度下
		  yanse.cdata[0]=*(buf+11);
      yanse.cdata[1]=*(buf+12);
		
		  char0=*(buf+13);
		  char1=*(buf+14);
			
			//显示接收的数据,看下对不 对
			sprintf(disbuf,"%0.2f",xzuobiao.fdata);
			OLED_ShowString(0,0,disbuf);
			
			sprintf(disbuf,"%0.2f",yzuobiao.fdata);
			OLED_ShowString(64,1,disbuf);
			
			OLED_ShowNum(0,2,zhijing.intdata,5,12);
			OLED_ShowNum(0,3,yanse.intdata,5,12);
			
			OLED_ShowChar(0,4,char0);
			OLED_ShowChar(48,4,char1);
		}
		break;
		
		//********************************************************
		case 0xd1://接收到0xd1
			//判断一下帧尾是不是相等
			  Message1[0]=*(buf+2) ; //0xba
			  Message1[1]=*(buf+3) ; //校验码	Message1[1]=*(buf+3) ; //校验码
		 //判断帧尾是不是相等
		    if(Message1[0]==0xba)
						if(Message1[1]==(0xab+0xd1+0xba)%256); //校验码是不是相等
								flagCode=0;//二维码扫描指令收到,停止发送二维码指令
		    OLED_ShowChar(30,5,'m');
		    temp0=Str_Long(Message1,5) ;
// 		    OLED_ShowNum(32,0,  temp0,5,12);//得到对应的任务号
// 				OLED_ShowString(10,3,"Fun4OK"); 
// 				OLED_ShowNum(100,0,Message1[0],3,12);//得到对应的任务号0xba==186
// 				OLED_ShowChar(100,5,FunCode);
				FunCode=0x00;
				break;

		//*********************************************************
		default:break;
	}


}

/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0()
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	ET0 = 1;        //使能T0中断
	TR0 = 1;		//定时器0开始计时
   
}
/* T0中断服务函数,执行串口接收监控和蜂鸣器驱动 */
void InterruptTimer0() interrupt 1
{
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
  UartRxMonitor(1);  //串口接收监控
}



// /******************************************************************
// 功能:将一个字符串转为32位长整型变量,比如"1234"转为1234
// 参数:str:指向待转换的字符串           
// 返回:转换后的数值										       
//  ******************************************** **********************/ 
// unsigned long Str_Long(char *str) 
// {
// 	 unsigned long temp=0;
// 	 unsigned long fact=1;
// 	 unsigned char len=strlen(str);	// <string.h>头文件包含strlen()函数	
// 	 unsigned char i;		// strlen()函数计算的字符串长度不包含最后一个空字符(值0)
// 	 for(i=len;i>0;i--)															   
// 	 {
// 		temp+=((str[i-1]-0x30)*fact);  // 数组下标从0开始
// 		fact*=10;
// 	 }
// 	 return temp;
// }


/******************************************************************
功能:将一个字符串转为32位长整型变量,比如"1234"转为1234
参数:str:指向待转换的字符串           
返回:转换后的数值										       
 ******************************************** **********************/ 
unsigned long Str_Long(char *str,unsigned char len) 
{
	 unsigned long temp=0;
	 unsigned long fact=1;
	// unsigned char len=strlen(str);	// <string.h>头文件包含strlen()函数	
	 unsigned char i;		// strlen()函数计算的字符串长度不包含最后一个空字符(值0)
	 for(i=len;i>0;i--)															   
	 {
		temp+=((str[i-1]-0x30)*fact);  // 数组下标从0开始
		fact*=10;
	 }
	 return temp;
}



uart2.h

#include "stc8a8k.h"

#define FOSC            11059200UL
#define BRT             (65536 - FOSC / 9600 / 4)

extern unsigned  char num23;	
//使用定时器2做波特率发生器
//串口2:P10 Rxd2;P11 TXD2
#define S2_S0 0x01              //P_SW2.0
//***********************************************************在主函数中定义,这里是引用别个文件定义的变量
extern bit flagFrame ;  //帧接收完成标志,即接收到一帧新数据
extern bit flagTxd ;    //单字节发送完成标志,用来替代TXD中断标志位
extern unsigned char cntRxd ;   //接收字节计数器
extern unsigned char pdata bufRxd[64];  //接收字节缓冲区
//*********************************************************************

void UART2_init(void);//初始化,9600,1T模式
unsigned char CheckSum(unsigned char *ptr, unsigned char len);//校验和
void sendcombytesUART2(unsigned char *ptr, unsigned char len);
void UartRxMonitor(unsigned char ms);
extern void UartAction(unsigned char *buf, unsigned char len);
void UartDriver();
void UART_Send_Byte(unsigned char dat);

uart2.c

#include "usart2.h"
#include "oled.h"
#include "delay.h"
#include <string.h>	  
extern unsigned char StartChar;//帧头

void UART2_init(void)
{		 

  S2CON = 0x10;		//8位数据,可变波特率
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0xE0;		//设定定时初值
	T2H = 0xFE;		//设定定时初值
	AUXR |= 0x10;		//启动定时器2
	
}

//##################################################################################
void Uart2Isr() interrupt 8 using 1 // 串行口2中断函数
{ 
	
	//发送
	if(S2CON&0x02)	   // 0x02=0000 0010,发送中断标志 S2TI=1
	{
		S2CON&=0xFD;   // 0xFD=1111 1101,清零发送中断标志 S2TI=0,		
	}
	//接受到1个字节//接收到新字节
	else if(S2CON&0x01)	   // 0x01=0000 0001,接收中断标志 S2RI=1
	{
	
		S2CON&=0xFE;   // 0xFE=1111 1110,清零接收中断标志 S2RI=0,
// 		OLED_ShowString(0,4,"rees");
// 		delay_tms(5);
// 		num23 = S2BUF;
// 		 OLED_ShowChar(110,3,'m');
// 		num23++;
// 		S2BUF = num23;   // 启动数据发送过程
		
		 if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
        {                            //保存接收字节,并递增计数器
         	if(cntRxd==0)	 //判断第一个字节
					{
						bufRxd[cntRxd] = S2BUF;//将第一个的字节,放到缓冲区
					
					  if(bufRxd[cntRxd]==StartChar)//判断是不是帧头
				   {
						    cntRxd=1;//是帧头,开始接受
						   
			      }	
						else
						{
							
							cntRxd=0;//不是的话,等到接受到帧头
							
						}
					}
					else//后面开始不断接受
					{
					
						bufRxd[cntRxd] = S2BUF;
						cntRxd++;	
					}						
					
        }
	}
}
/*********************************************/
unsigned char CheckSum(unsigned char *ptr, unsigned char len)
{
   	unsigned char i; 
	  unsigned char a;	   
	  unsigned int Value=0;
	  for(i=0;i<len;i++)  // len结束后第一个字节为接收到的校验和
	  {
		  Value = Value + ptr[i];   
	   }
	   a=Value;            // 长送短,传送完整低字节
	   return(a); 
}
/*********************************************/
//发送一帧完整数据
void sendcombytesUART2(unsigned char *ptr, unsigned char len)
{  
	unsigned char i; 	
	for(i=0;i<len;i++)
	{
		S2BUF=*(ptr+i);	  
		while(S2CON&0x02);
		S2CON&=0xFD;  
	} 	
}

/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead(unsigned char *buf, unsigned char len)
{
    unsigned char i;
    
    if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,
    {                  //读取长度设置为实际接收到的数据长度
        len = cntRxd;
    }
    for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上
    {
        *buf++ = bufRxd[i];
    }
    cntRxd = 0;  //接收计数器清零
    
    return len;  //返回实际读取长度
}

/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
    static unsigned char cntbkp = 0;
    static unsigned char idletmr = 0;

    if (cntRxd > 0)  //接收计数器大于零时,监控总线空闲时间
    {
        if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时
        {
            
					  cntbkp = cntRxd;
            idletmr = 0;
        }
        else                   //接收计数器未改变,即总线空闲时,累积空闲时间
        {
            if (idletmr < 30)  //空闲计时小于30ms时,持续累加
            {
                idletmr += ms;
                if (idletmr >= 30)  //空闲时间达到30ms时,即判定为一帧接收完毕
                {
                    flagFrame = 1;  //设置帧接收完成标志
                }
            }
        }
    }
    else
    {
        cntbkp = 0;
    }
}

/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver()
{
    unsigned char len;
    unsigned char pdata buf[40];

	  //串口接收监控中改变
    if (flagFrame) //有命令到达时,读取处理该命令
    {
        flagFrame = 0;
        len = UartRead(buf, sizeof(buf));  //将接收到的命令读取到缓冲区中
        UartAction(buf, len);  //传递数据帧,调用动作执行函数
    }
}


/**************************************************************************
功能:STC15单片机的串口发送字节的函数
参数:dat:要发送的一个字节   
IE2  XX ET4 ET3 ES4 ES3 ET2 ESPI ES2
     0   0  0   0    0   0   0    1
ES2=1
IE2 &=~0x01
**************************************************************************/
void UART_Send_Byte(unsigned char dat)
{
	IE2 &=~0x01;		 // 使用查询发送结束方式,禁止中断干预    IE2 = ES2;     0x01                             //使能串口中断
	S2BUF = dat;
	while(S2CON&0x02);
	S2CON&=0xFD;
// 	while(!TI);	    
//  	TI=0;	 //此句可以不要,不影响后面数据的发送,只供代码查询数据是否发送完成
	IE2 |=0x01;
}	
/**************************************************************************		S2BUF=*(ptr+i);	  
		while(S2CON&0x02);
		S2CON&=0xFD;
功能:STC15单片机的串口发送0d 0a ,即回车换行 
注:此函数就是发送0d 0a这两个字节,在"串口助手"上会有回车换行的效果
 **************************************************************************/  
// void UART_Send_Enter()
// {
// 	UART_Send_Byte(0x0d); // 转义字符常量\r,ASCII码值(10进制)=13,光标移到本行行首
// 	UART_Send_Byte(0x0a); // 转义字符常量\n,ASCII码值(10进制)=10,光标移到下行行首
// }

/**************************************************************************
功能:16进制转ASCII码函数
 **************************************************************************/
unsigned char Hex_ASCII(unsigned int hex,char *str)
{
	unsigned char temp=0;
	
	temp=((hex&0xf000)>>12);	  // 4位1表示范围0_9_A_F
	str[0]=(temp>=10)?(temp-10+'A'):(temp+0x30);
		// 0_9的ASCII码是0_9+ 0x30,
	    // A_F的ASCII码: A代表数值10,A的ASCII码是65,因此数值+55=ASCII
		// 因此算式(temp-10+'A')=(temp-10+65)=(temp+55)
		// 分析依据:ASCII码表
	temp=((hex&0x0f00)>>8);
	str[1]=(temp>=10)?(temp-10+'A'):(temp+0x30);
	
	temp=((hex&0x00f0)>>4);
	str[2]=(temp>=10)?(temp-10+'A'):(temp+0x30);
	
	temp=((hex&0x000f)>>0);
	str[3]=(temp>=10)?(temp-10+'A'):(temp+0x30);
	
	str[4]=0;	    // 由于要使用KEIL自带的字符串处理函数处理,必须有结束标记。 
	
	return 0;
} 



// /**************************************************************************
// 功能:51单片机的串口发送调试信息(二进制数据显示)	  
// 参数:dat:需要按2进制形式显示变量
//  **************************************************************************/
// void UART_Send_binary(unsigned char dat)
// {
// 	unsigned char i;
// 	unsigned char a[17];
// 	for(i=0;i<8;i++)
// 	{
// 		a[i]=((dat<<i)&0x80)?'1':'0';
// 	}
// 	a[i]=0;
// 	for(i=0;i<strlen(a);i++)
// 	{
// 		UART_Send_Byte(a[i]);
// 		UART_Send_Byte(' ');
// 	}

// }



oled.h

//	 
//  功能描述   : OLED 4接口演示例程(51系列)
//              说明: 
//              ----------------------------------------------------------------
//              GND    电源地
//              VCC  接5V或3.3v电源
//              D0   接P10(SCL)
//              D1   接P11(SDA)
//              RES  接P12
//              DC   接P13
//              CS   接P14              

//******************************************************************************/
#ifndef __OLED_H
#define __OLED_H			  	 
#include "stc8a8k.h"

//OLED模式设置
//0:4线串行模式
//1:并行8080模式
#define OLED_MODE 0
#define SIZE 12
#define XLevelL		0x00
#define XLevelH		0x10
#define Max_Column	128
#define Max_Row		64
#define	Brightness	0xFF 
#define X_WIDTH 	128
#define Y_WIDTH 	64	    

//--------------------------------- 
//  d0    d1  res  dc  cs
//  scl  sdin rst  
//-----------------OLED端口定义----------------  
// sbit OLED_SCLK= P0^0;
// sbit OLED_SDIN= P0^1;
// sbit OLED_RST=P0^2;
// sbit OLED_DC=P0^3;
// sbit OLED_CS=P0^4;
sbit OLED_SCLK= P7^4;
sbit OLED_SDIN= P7^5;
sbit OLED_RST=P7^6;
sbit OLED_DC=P7^7;
sbit OLED_CS=P4^3;

#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据


void OLED_SCLK_Clr();//CLK
void OLED_SCLK_Set();

void OLED_SDIN_Clr();//DIN
void OLED_SDIN_Set();

void OLED_RST_Clr();//RES
void OLED_RST_Set();

void OLED_DC_Clr();//DC
void OLED_DC_Set();

void OLED_CS_Clr();//CS
void OLED_CS_Set();

//OLED控制用函数
void delay_tmsOLED(unsigned int ms0);	//@11.0592MHz--11-190-766us;11-195--785us;20--x--1000
void delay4us_tOLED(int us);		//@11.0592MHz---4us

void OLED_WR_Byte(u8 dat,u8 cmd);	    
void OLED_Display_On(void);
void OLED_Display_Off(void);	   							   		    
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr);
void OLED_ShowNum(u8 x,u8 y,u16 num,u8 len,u8 size0);
void OLED_ShowString(u8 x,u8 y, u8 *p);	 
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowFloatii(u8 x,u8 y,float num,u8 ii);
#endif  
	 




oled.c

// //--------------------------------- 
// //  d0    d1  res  dc  cs
// //  scl  sdin rst  
// //-----------------OLED端口定义----------------  
// sbit OLED_SCLK= P0^0;
// sbit OLED_SDIN= P0^1;
// sbit OLED_RST=P0^2;
// sbit OLED_DC=P0^3;
// sbit OLED_CS=P0^4;
//******************************************************************************/

#include "oled.h"
#include "oledfont.h"  	 

#if OLED_MODE==1
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
	DATAOUT(dat);	    
	if(cmd)
	  OLED_DC_Set();
	else 
	  OLED_DC_Clr();		   
	OLED_CS_Clr();
	OLED_WR_Clr();	 
	OLED_WR_Set();
	OLED_CS_Set();	  
	OLED_DC_Set();	 
} 	    	    
#else
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{	
	u8 i;			  
	if(cmd)
	  OLED_DC_Set();
	else 
	  OLED_DC_Clr();	
delay4us_tOLED(1);	
	OLED_CS_Clr();
	delay4us_tOLED(1);	
	for(i=0;i<8;i++)
	{			  
		OLED_SCLK_Clr();
		delay4us_tOLED(1);	
		if(dat&0x80)
		   OLED_SDIN_Set();
		else 
		   OLED_SDIN_Clr();
		OLED_SCLK_Set();
		dat<<=1;   
	}	
delay4us_tOLED(1);		
	OLED_CS_Set();
	delay4us_tOLED(1);	
	OLED_DC_Set();   	  
} 
#endif
	void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 
	OLED_WR_Byte(0xb0+y,OLED_CMD);
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD); 
}   	  
//开启OLED显示    
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}		   			 
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
void OLED_Clear(void)  
{  
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
	} //更新显示
}


//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
void OLED_ShowChar(u8 x,u8 y,u8 chr)
{      	
	unsigned char c=0,i=0;	
		c=chr-' ';//得到偏移后的值			
		if(x>Max_Column-1){x=0;y=y+2;}
				OLED_Set_Pos(x,y+1);
				for(i=0;i<6;i++)
				OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
//m^n函数
u16 oled_pow(u8 m,u8 n)
{
	u16 result=1;	 
	while(n--)result*=m;    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小,这里是12
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(u8 x,u8 y,u16 num,u8 len,u8 size0)
{         	
	u8 t,temp;
	u8 enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+((size0/2)+1)*t,y,' ');//这里我自己修改了一下。不如数据会重叠
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+((size0/2)+1)*t,y,temp+'0'); //这里我自己修改了一下。不如数据会重叠
	}
} 
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr)
{
	unsigned char j=0;
	while (chr[j]!='\0')
	{		OLED_ShowChar(x,y,chr[j]);
			x+=8;
		if(x>120){x=0;y+=2;}
			j++;
	}
}

//初始化SSD1306					    
void OLED_Init(void)
{ 	
  //设置端口的IO模式,不同引脚不一样 ====================********%%%    注意修改
// sbit OLED_SCLK= P0^2;
// sbit OLED_SDIN= P0^3;
// sbit OLED_RST=P0^4;
// sbit OLED_DC=P2^0;
// sbit OLED_CS=P0^6;
	//准双向口模式
	// --------------------------
	//     P07 06  05 04   03 02 01 00
	//P0M0  x   0   x  0   0  0  x  x     ===0xa3
	//P0M1  x   0   x  0   0  0  x  x     ===0xa3
	//准双向口模式
	// --------------------------
	//     P27 26  25 24  23 22 21 20
	//P2M0  x   x  x  x  x  x  x    0    ==0xfe
	//P2M1  x   x   x  x   x  x  x  0	   ==0xfe
	
  P4M0 =0;//与操作 清零
	P4M1 =0;
	
	P7M0=0;
	P7M1=0;
	/
	
	delay_tmsOLED(5);
  OLED_RST_Set();
	delay_tmsOLED(5);
	OLED_RST_Clr();
	delay_tmsOLED(5);
	OLED_RST_Set(); 
					  
	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WR_Byte(0x02,OLED_CMD);//
	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
	
	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 
	OLED_Clear();
	OLED_Set_Pos(0,0); 	
}  
//
void OLED_SCLK_Clr()//CLK
{
    OLED_SCLK=0;
}
///
void OLED_SCLK_Set()
{
   OLED_SCLK=1;
}
//
void OLED_SDIN_Clr()//DIN
{
	OLED_SDIN=0;
}

void OLED_SDIN_Set()
{
  OLED_SDIN=1;
}
//
void OLED_RST_Clr()//RES
{
	OLED_RST=0;
}
/
void OLED_RST_Set()
{
	OLED_RST=1;
}
///
void OLED_DC_Clr()//DC
{
  OLED_DC=0;
}
/
void OLED_DC_Set()
{
	OLED_DC=1;
}
///
void OLED_CS_Clr()//CS
{
    OLED_CS=0;
}
///
void OLED_CS_Set()
{
    OLED_CS=1;
}



//
void OLED_ShowFloatii(u8 x,u8 y,float num,u8 ii)
{
	  u8 i,j,mm;
	  float mmd;
	  i=x*8;//横轴每8个像素点,移位一个数字;
	  j=y;//纵轴,每个换到新的行
	  mm=8;//
	  mmd=0.125;//等于1/8=0.125
	 
    switch(ii)
		{
		
			case 43://1234.456
				OLED_ShowNum(i,j,(int)(num/1000)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num/100)%10,1,12);	//i+8
				OLED_ShowNum(i+2*mm,j,(int)(num/10)%10,1,12);//i+16
			 	OLED_ShowNum(i+3*mm,j,(int)(num)%10,1,12);//i+16
			//OLED_ShowString((i+3*mm)*mmd,j,".");//i+24
			  OLED_ShowString(i+4*mm,j,".");//i+24
				OLED_ShowNum(i+5*mm,j,(int)(num*10)%10,1,12);//i+32
				OLED_ShowNum(i+6*mm,j,(int)(num*100)%10,1,12);	
				OLED_ShowNum(i+7*mm,j,(int)(num*1000)%10,1,12);	
				break;
			case 42://1234.45
				OLED_ShowNum(i,j,(int)(num/1000)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num/100)%10,1,12);	//i+8
				OLED_ShowNum(i+2*mm,j,(int)(num/10)%10,1,12);//i+16
			 	OLED_ShowNum(i+3*mm,j,(int)(num)%10,1,12);//i+16
			//OLED_ShowString((i+3*mm)*mmd,j,".");//i+24
			  OLED_ShowString(i+4*mm,j,".");//i+24
				OLED_ShowNum(i+5*mm,j,(int)(num*10)%10,1,12);//i+32
				OLED_ShowNum(i+6*mm,j,(int)(num*100)%10,1,12);	
				break;
			
			case 33://123.456
				OLED_ShowNum(i,j,(int)(num/100)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num/10)%10,1,12);	//i+8
				OLED_ShowNum(i+2*mm,j,(int)(num*1)%10,1,12);//i+16
			//OLED_ShowString((i+3*mm)*mmd,j,".");//i+24
			  OLED_ShowString(i+3*mm,j,".");//i+24
				OLED_ShowNum(i+4*mm,j,(int)(num*100)%10,1,12);//i+32
				OLED_ShowNum(i+5*mm,j,(int)(num*100)%10,1,12);	
				OLED_ShowNum(i+6*mm,j,(int)(num*1000)%10,1,12);	
				break;
			case 32://123.45*100=12345            1,5
				//1---12345/10000  2---12345/1000=12  3---12345/100=123
			//4---12345/10=1234  5---12345%10
				OLED_ShowNum(i,j,(int)(num/100)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num/10)%10,1,12);		//
				OLED_ShowNum(i+2*mm,j,(int)(num*10)%10,1,12);		//
				//OLED_ShowString((i+3*mm)*mmd,j,".");//
		  	OLED_ShowString(i+3*mm,j,".");//
				OLED_ShowNum(i+4*mm,j,(int)(num*10)%10,1,12);	
				OLED_ShowNum(i+5*mm,j,(int)(num*100)%10,1,12);	
				break;
			case 31:
				//123.4====1234
				OLED_ShowNum(i,j,(int)(num/100)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num/10)%10,1,12);		//
				OLED_ShowNum(i+2*mm,j,(int)(num*1)%10,1,12);		//
			//	OLED_ShowString((i+3*mm)*mmd,j,".");//
		   	OLED_ShowString(i+3*mm,j,".");
				OLED_ShowNum(i+4*mm,j,(int)(num*10)%10,1,12);		
				break;
			case 23:
				//12.345===12345
				OLED_ShowNum(i,j,(int)(num/10)%10,1,12); //
				OLED_ShowNum(i+mm,j,(int)(num*1)%10,1,12);		//
			//	OLED_ShowString((i+2*mm)*mmd,j,".");//
				OLED_ShowString(i+2*mm,j,".");
				OLED_ShowNum(i+3*mm,j,(int)(num*10)%10,1,12);//
				OLED_ShowNum(i+4*mm,j,(int)(num*100)%10,1,12);	
				OLED_ShowNum(i+5*mm,j,(int)(num*1000)%10,1,12);
				break;
			case 22:
				//12.34---1234--
				OLED_ShowNum(i,j,(int)(num/10)%10,1,12);		//
				OLED_ShowNum(i+mm,j,(int)(num)%10,1,12);//
   		//	OLED_ShowString((i+2*mm)*mmd,j,".");//
			  OLED_ShowString(i+2*mm,j,".");
				OLED_ShowNum(i+3*mm,j,(int)(num*10)%10,1,12);	
				OLED_ShowNum(i+4*mm,j,(int)(num*100)%10,1,12);
				break;
			case 21:
				//12.3---123--
				OLED_ShowNum(i,j,(int)(num/10)%10,1,12);//
				OLED_ShowNum(i+mm,j,(int)(num)%10,1,12);	
			  //OLED_ShowString((i+2*mm)*mmd,j,".");//	
			  OLED_ShowString(i+2*mm,j,".");
				OLED_ShowNum(i+3*mm,j,(int)(num*10)%10,1,12);
				break;
			case 13:
				//1.234===1234
				OLED_ShowNum(i,j,(int)(num)%10,1,12);		//
   		//	OLED_ShowString((i+mm)*mmd,j,".");//	
			  OLED_ShowString(i+2*mm,j,".");
			  OLED_ShowNum(i+2*mm,j,(int)(num*10)%10,1,12);//
				OLED_ShowNum(i+3*mm,j,(int)(num*100)%10,1,12);	
				OLED_ShowNum(i+4*mm,j,(int)(num*1000)%10,1,12);
				break;
			case 12:
				//1.23===123
			  OLED_ShowNum(i,j,(int)(num)%10,1,12);//
			 // OLED_ShowString((i+mm)*mmd,j,".");//	
			  OLED_ShowString(i+mm,j,".");
				OLED_ShowNum(i+2*mm,j,(int)(num*10)%10,1,12);	
				OLED_ShowNum(i+3*mm,j,(int)(num*100)%10,1,12);
				break;
			case 11:
				//1.2===12
				OLED_ShowNum(i,j,(int)(num*10/10)%10,1,12);
   			//OLED_ShowString((i+mm)*mmd,j,".");//	
			   OLED_ShowString(i+mm,j,".");
				OLED_ShowNum(i+2*mm,j,(int)(num*10)%10,1,12);
				break;
			default :break;
			
		}
}

//
void delay_tmsOLED(unsigned int ms0)		//@11.0592MHz--11-190-766us;11-195--785us;20--x--1000
{                                    //
	unsigned char i, j;
	unsigned int tms;
	for(tms=ms0;tms>0;tms--)
		for(i=20;i>0;i--)
			for(j=136;j>0;j--);
}
/
void delay4us_tOLED(int us)		//@11.0592MHz---4us
{
	int i;
	for(i=us;i>0;i--);
}

delay.h



#ifndef __DELAY_H
#define __DELAY_H		
void delay_tus(unsigned int tus);
void delay_tms(unsigned int tms);
#endif  

delay.c

#include "delay.h"
void delay_tus(unsigned int tus)//@11.0592MHz
{
	unsigned char i;
	i = tus;
	while (--i);
}

void delay_tms(unsigned int tms)
{
	unsigned char i, j,ttt;
  for(ttt=tms;ttt>0;ttt--)
	{	
	  i = 15;
		j = 90;
		do
		{
			while (--j);
		} while (--i);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值