⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 temp_16.c

📁 采用过采样技术实现16位精度温度采样 采用过采样技术实现16位精度温度采样 采用过采样技术实现16位精度温度采样
💻 C
字号:
/**********************************************************************************
*本程序对片内温度传感器进行采样,并将其值放到液晶上显示出来
**********************************************************************************/
#include "c8051F040.h"

#define uchar unsigned char
#define uint unsigned int
#define Stack_len 16
sfr16 ADC0val =0xbe;
bit flag=0;

uchar temp_l;
uchar temp_h;
uint temp_hl;
long temp;
uint kk;
float tempval;

uchar xdata virt_port;
bit SPI_BUSY;
sbit LcdCs=P2^5;

uchar st_index=0;
unsigned long total;
uint xdata mystack[Stack_len];
uchar xdata tab[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
//tabl是对应的数码表:0123456789 v

void os_init();
void port_init();
void adc_init();
void spi_init();
void writecode(uchar ins);
void writedata(uchar d);
void lcdinit();
void writelcd(uchar spi_data);
void lcdchar (void);
void lcdchar_hex(void);

/*********************************************************************
*
*主函数
**********************************************************************/
void main()
{
	uchar i,j,k;
//	uchar m;
    WDTCN = 0xDE;                                           // 关闭看门狗
	WDTCN = 0xAD;
	os_init();
    adc_init();
    port_init();
	spi_init();
	lcdinit();
	SFRPAGE   = CONFIG_PAGE;
 	EIE2      = 0x02;                              //允许ADC中断
	IE        = 0x80;							   //允许所有中断
     
	EIE1      = 0x01;
	EA=1;
	i=0;
//	m=0;
	while(1)
	{
		SFRPAGE   = ADC0_PAGE;
	 	AD0INT=0;
	 	AD0BUSY=1;
	  	while(AD0INT)
		if(flag)
		{	flag=0;
	 		lcdinit();
	 		lcdchar();
// 			lcdchar_hex();
//第二行显示和延时
	 		writecode(0xb0);
			j=i/16;
			k=i%16;
	 		writedata(tab[j]);
	 		writedata(tab[k]);		
			i++;
			for(j=0;j<250;j++)
			for(j=0;j<250;j++)
			for(j=0;j<250;j++);
 			writedata(' ');
			for(j=0;j<250;j++)
			for(j=0;j<250;j++)
			for(j=0;j<250;j++);
 			writedata(' ');
			for(j=0;j<250;j++)
			for(j=0;j<250;j++)
			for(j=0;j<250;j++);
	 		writedata(' ');
			for(j=0;j<250;j++)
			for(j=0;j<250;j++)
			for(j=0;j<250;j++);
	 		writedata(' ');
		}
/* 		lcdinit();
		writedata('V');
	 	writedata('D');			
		writecode(0xb0);
		j=m/16;
		k=m%16;
		writedata(tab[j]);
	 	writedata(tab[k]);		
		m++;
		if(m>=Stack_len) m=0;
*/
	}	
}
/*********************************************************************
*
*晶振选择及时钟初始化函数
**********************************************************************/
void os_init()
{
    int i = 0;
    SFRPAGE   = CONFIG_PAGE;
    OSCXCN    = 0x67;
    for (i = 0; i < 3000; i++);                   // 等待外部晶振稳定
  //  while ((OSCXCN & 0x80) == 0);
    CLKSEL    = 0x01;							  //选择系统时钟频率

}
/*********************************************************************
*
*12位ADC初始化
**********************************************************************/
void adc_init()
{
    SFRPAGE   = ADC0_PAGE;
    REF0CN    = 0x07;
    AMX0SL    = 0x08;
	ADC0CN    = 0x80;				            //向AD0BUSY写1启动转换
}
/*********************************************************************
*
*ADC中断函数
*********************************************************************/
void adc_isr () interrupt 15
{   if(AD0INT==1)
    {   mystack[st_index]=ADC0val;
		st_index++;
		if(st_index>=Stack_len)
		{
	  		st_index=0;
			flag=1;	
		}
	}
	SFRPAGE   = ADC0_PAGE;
	AD0INT=0;
}
void port_init()
{
    SFRPAGE   = CONFIG_PAGE;
   	P0MDOUT=0xff;
    XBR0      = 0x06;
    XBR2      = 0x40;
}
void spi_init()
{
    SFRPAGE   = SPI0_PAGE;
    SPI0CFG   = 0x40;
    SPI0CN    = 0x01;
    SPI0CKR   = 0x6D;
}
void delay1us(void)
{
	uchar xdata i;
	for(i=10;i>0;i--);
} 

void writelcd(uchar spi_data)	   //向LV595写数据以SPI方式
{
  	uint xdata i,j,k;
 	for(i=0;i<9;i++);
	LcdCs=0;
	delay1us();	
	SPI_BUSY=1;
	SFRPAGE   = SPI0_PAGE;
	SPI0DAT=spi_data;
	for(j=0;j<500;j++)
	{
	   	if(!SPI_BUSY)break;
	} 
	delay1us();
	LcdCs=1;
	delay1us();
	delay1us();
	delay1us();
	delay1us();
	delay1us();
	delay1us();
	for(k=0;k<5000;k++);
}
void writecode(uchar ins)				    //向液晶控制模块写命令
{
      uchar xdata t;
	  uint xdata j;
	  for(j=0;j<500;j++);	
	  virt_port|=ins&0xf0;					//取高字节向1602写数据 
	  writelcd(virt_port);					//先写高4位后再写低4位 这是在选择四个数据线的时候
	  virt_port|=0x08;						  
	  writelcd(virt_port);					//使能E脚为高电平
      virt_port&=~0x08;					
	  writelcd(virt_port);					//使能E脚为低电平
      t=ins<<4;             
      virt_port|=t&0xf0;          			//取低字节向1602写数据
	  writelcd(virt_port);
      virt_port|=0x08;						//使能E脚为高电平
	  writelcd(virt_port);
      virt_port&=~0x08;					    //使能E脚为低电平
	  writelcd(virt_port);
      virt_port=0;
	  writelcd(virt_port);
}
void writedata(uchar d)					   //写数据到1602
{
	uchar xdata i,t;
	uint xdata j;
    for(j=0;j<500;j++);		
    virt_port|=0x02;					   //光标返回指令
	writelcd(virt_port);
    virt_port|=d&0xf0;				   //取高字节数据给数据寄存器
	writelcd(virt_port);
    virt_port|=0x08;                     //使能E脚为高电平
	writelcd(virt_port);
    virt_port&=0xf7;      			   //使能E脚为低电平
	writelcd(virt_port);
    virt_port&=0x07;					   //设置光标右移,文字也右移
    writelcd(virt_port);     
    t=d&0x0f;
    virt_port|=t<<4;					   //取低字节数据给数据寄存器
	writelcd(virt_port);
	virt_port|=0x08;      			   //使能E脚为高电平
	writelcd(virt_port);
    for(i=3;i>0;i--); 
    virt_port&=0xf7;                     //使能E脚为低电平
	writelcd(virt_port);
    virt_port=0;						   //数据清零
	writelcd(virt_port);
}
void lcdchar(void)
{
	uchar a,i;
	uint zhengshu;
	float xiaoshu;
	
	for(i=0,total=0;i<Stack_len;i++)
	{total+=mystack[i];}
	total/=1L;
	tempval=(float)total/65536.0;
	tempval*=2.43;
	tempval-=0.776;
	tempval/=0.00286;		//将测量值转化成真实温度值

	zhengshu=tempval;         //取整数
	xiaoshu=tempval-zhengshu;       //取小数
	zhengshu%=100;           //不要大于100的数
	a=zhengshu/10;				//十位数
	writedata(tab[a]);	 
	a=zhengshu%10;				//个位数
	writedata(tab[a]);	 
	writedata('.');	  
	xiaoshu*=10;				//十分位
	a=xiaoshu;
	writedata(tab[a]);	 
	xiaoshu-=a;					//百分位
  	xiaoshu*=10;
	a=xiaoshu;
	writedata(tab[a]);	
	xiaoshu-=a;					//千分位
	xiaoshu*=10;		
	a=xiaoshu;
	writedata(tab[a]);	
	xiaoshu-=a;					//万分位
	xiaoshu*=10;
	a=xiaoshu;
	writedata(tab[a]);	
	writedata(' ');
    writedata('C');  
}
void lcdchar_hex(void)
{
//********测试ADC采样数据寄存器处理(采用正数乘除法)     
	uchar a,b,c,d,tem;
	uint tem1;
	temp_hl=(uint)temp_h;
    temp_hl=temp_hl*256;
	temp_hl=temp_hl+(uint)temp_l;
//显示高位十六进制
	tem=temp_h;
//	b=tem&0x0f;
//	a=tem>>4;
	b=tem%16;
	a=tem/16;
	writedata(tab[a]);
	writedata(tab[b]);   
//显示低位十六进制
	tem=temp_l;
//	b=tem&0x0F;
//	a=tem>>4;
	b=tem%16;
	a=tem/16;
	writedata(tab[a]);
	writedata(tab[b]);
//显示高低位十六进制
	tem1=temp_hl;
	tem=tem1/256;
	b=tem%16;
	a=tem/16;
	writedata(tab[a]);
	writedata(tab[b]);  
	tem=tem1%256; 
	d=tem%16;
	c=tem/16;
	writedata(tab[c]);
	writedata(tab[d]);  
/*************/ 
}              
void lcdinit()
{
      uint xdata i;	
      virt_port=0x00;
	  writelcd(virt_port);	     //RS脚为零写指令寄存器	 RW为低电平
      virt_port|=0x08;     	     //使能脚E=1
	  writelcd(virt_port);
 	  virt_port&=0xf7;    		 //使E=0使能脚发生跳变高--低
	  writelcd(virt_port);
	  for(i=1000;i>0;i--);	     //3次延时,重要!
	  for(i=8000;i>0;i--);		 //用延时代替查询	    
      virt_port=0;				 //写入20码,设置为4位总线方式,非常重要!!!!!
	  writelcd(virt_port);
      virt_port|=0x20;			 //只写高字节
	  writelcd(virt_port);
      virt_port|=0x08;           //E=1
	  writelcd(virt_port);
	  for(i=20;i>0;i--);		 //使命令执行
      virt_port&=0xf7;           //E=0
	  writelcd(virt_port);
	  for(i=10;i>0;i--);
      virt_port=0;
	  writelcd(virt_port);
      writecode(0x38);	    	//设两行显示,4线方式5*10字符显示
      for(i=50;i>0;i--);
	  writecode(0x06);			//光标右移
      for(i=50;i>0;i--);  
	  writecode(0x0c);		    //开显示指令
      for(i=50;i>0;i--);	 
      writecode(0x02);			//光标返回指令
      for(i=50;i>0;i--);
	  writecode(0x01);			//清屏指令
	  for(i=50;i>0;i--);
}
void spi_srs  () interrupt 6
{
	if(SPIF)		
	{
	  	SFRPAGE   = SPI0_PAGE;
	  	SPIF=0;
		SPI_BUSY=0;
	}
	if(WCOL)
	{
	   	SFRPAGE   = SPI0_PAGE;
		WCOL=0;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -