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

📄 temp.asm

📁 这个是基于单片机的温度测量的程序.这个可以测量外界的温度(除芯片的自身的温度外),并且可以手动设置温度的最高和最低值.如果温度低于最低或高于最高值
💻 ASM
字号:
//-------------------------------------------------------------------
// CYGNAL INTEGRATED PRODUCTS, INC.
//
// 文件: Temp_2.c
// 目标MCU: C8051F000,C8051F010
//
// 本程序将C8051Fxxx 的基底温度由硬件UART输出,波特率为115.2kbps,8个数据位,
// 无奇偶校验,一个停止位。假定在XTAL1和XTAL2之间连接一个11.0592MHz的晶体。
//
// 工具链:KEIL C51
//
// Make.bat 为:
// C:\Keil\C51\BIN\C51.EXE temp_2.c CD OE DB SB
// C:\Keil\C51\BIN\BL51.EXE temp_2.obj
//
//------------------------------------------------------------------
// 编译命令
//-------------------------------------------------------------------
// 编译器命令行选项
//-------------------------------------------------------------------
// 包含文件
//-------------------------------------------------------------------
#include <c8051f000.h> // SFR 声明
#include <stdio.h>
//-------------------------------------------------------------------
// 全局常数
//-------------------------------------------------------------------
#define ON 1
#define OFF 0
#define XTLVLD_BIT 0x80 // OSCXCN.7 晶体振荡器有效标志
#define TC_20MS 18432 // 定时器在 11.0592MHz/12时对应于
// 20ms的嘀答数
#define SYSCLK             11059200  // SYSCLK in Hz (16 MHz internal
#define TIMER_PRESCALER            12  // Based on Timer2 CKCON settings

#define LED_TOGGLE_RATE            10  // LED toggle rate in milliseconds
                                       // if LED_TOGGLE_RATE = 1, the LED will
                                       // be on for 1 millisecond and off for
                                       // 1 millisecond

// There are SYSCLK/TIMER_PRESCALER timer ticks per second, so
// SYSCLK/TIMER_PRESCALER/1000 timer ticks per millisecond.
#define TIMER_TICKS_PER_MS  SYSCLK/TIMER_PRESCALER/1000

// Note: LED_TOGGLE_RATE*TIMER_TICKS_PER_MS should not exceed 65535 (0xFFFF)
// for the 16-bit timer

#define AUX1     TIMER_TICKS_PER_MS*LED_TOGGLE_RATE/10
#define TIMER_RELOAD            AUX2  // Reload value for Timer2
#define AUX2     -AUX1
sbit rd     = P1^7;
sbit re     = P1^5;
sbit wr		= P1^6;
sbit addr0	= P1^0;
sbit addr1	= P1^1;
sbit addr2	= P1^2;
sbit addr3	= P1^3;
sbit addr4	= P1^4;

sbit data0	= P2^0;
sbit data1	= P2^1;
sbit data2	= P2^2;
sbit data3	= P2^3;
sbit lcd_en = P3^0;

//-------------------------------------------------------------------
// 函数原型
//-------------------------------------------------------------------
void sysclk_init (void);
void xbar_init (void);

void ADC_init (void);
void ADC_enable (void);
void Timer3_init (void);
void ADC_isr (void);
void write (int addr, int datain);
unsigned int read();
void delay(int time_10ms);
void Timer0_Init(void);  //buchang


//-------------------------------------------------------------------
// 全局变量
//-------------------------------------------------------------------
long temperature; // 以百分之一度表示的温度值
unsigned idata temp[16]; // 温度采样值的循环缓冲区
int temp_ptr; // 指向 temp[]的指针
int temp_int; // 温度值的整数部分
int temp_frac; // 温度值的小数部分(以百分之一度为单位)
int n,m,l;    //延时程序中用
int max=17;  // 最高
int min=12;  // 最高
int maxa,maxb,mina,minb;
int tem;
int xz;
int lasttem=0,pasttem=0;

int hour=0,minute=0,second=0,percent=0; 
void Timer0_ISR (void) interrupt 1
{ int lasttem;
    static int mm=0,ff=0;
    second++;

	if(second==10)     //延迟10NS
   {pasttem=tem;       //读取当时测得温度
    write(6,pasttem/10);
	write(5,pasttem%10);
	delay(500); 
	write(6,max/10);
    write(5,max%10);}
	
    if(second==200)   //延迟200NS
	{lasttem=tem;      //读取当时测得温度
	write(8,1);
	delay(100);
	write(8,0);
	xz=lasttem-pasttem;//	得到芯片温度
	if(xz<0)
	xz=0;
	write(6,xz/10);
	write(5,xz%10);
	
	delay(1000);
	write(6,max/10);
    write(5,max%10); 
	write(2,(tem-xz)/10);//
    write(1,(tem-xz)%10);
	}
                        // Toggle the LED
    TF0 = 0;                            // Reset Interrupt
}

//-------------------------------------------------------------------
// 主程序
//-------------------------------------------------------------------
void main (void) 
{ 
unsigned int temp1,temp2,xor1,wei1,wei2,temp_wei;
  int i1=0,i2,i3,i4;
  int flag=0;
  int a,b,c,d;
  int tem;

tem=temperature;
  sysclk_init (); // 初始化振荡器
  xbar_init (); // 初始化交叉开关和GPIO
  Timer0_Init();
  Timer3_init (); // 初始化定时器3为 20ms 溢出
  ADC_init (); // 初始化 ADC 的输入为温度传感器
  ADC_enable (); // 允许 ADC转换结束中断
  temperature = 0L;
  temp_ptr = 0;
  lcd_en=0;

  EA =1; // 允许中断
  temp2=read();
  
write(0,15);
write(6,max/10);
write(5,max%10); 
write(4,min/10);
write(3,min%10); 
//write(3,11); 
write(2,(tem-xz)/10);
write(1,(tem-xz)%10);

  while (1)
   {
// 将以百分之一度表示的温度值转换成两个十进制数,整数部分和小数部分
temp1=read();
	if (temp1!=temp2) 
	{
    xor1=temp1^temp2; 
	delay(10);
    temp2=read();
    if (temp1==temp2) 
	{   
	    wei1=xor1%2;
		temp_wei=temp2;
	    if(wei1!=0)
		{
		   wei2=temp_wei%2;
		   if(wei2==0) 
		   {if(flag==1&&i1%2==0)
		   {min++;write(7,3);}
          if(flag==1&&i1%2==1)
		   {max++;write(7,5);}
		
		   mina=min/10;
		   minb=min%10;
           write(4,mina);
		   write(3,minb);
		   
		   maxa=max/10;
		   maxb=max%10;
           write(6,maxa);
		   write(5,maxb);
           
		   }

		}
		xor1>>=1;
	    wei1=xor1%2;
	    if(wei1!=0)
		{
           temp_wei>>=1;
		   wei2=temp_wei%2;
		   if(wei2==0) 
		   { 
		  if(flag==1&&i1%2==0)
		   {min--;write(7,3);}
          if(flag==1&&i1%2==1)
		  { max--;write(7,5); }
		   
		   mina=min/10;
		   minb=min%10;
		   write(4,mina);
		   write(3,minb);
          
		   maxa=max/10;
		   maxb=max%10;
           write(6,maxa);
		   write(5,maxb);
		    }

		}
		xor1>>=1;
	    wei1=xor1%2;
	    if(wei1!=0)
		{
           temp_wei>>=2;
		   wei2=temp_wei%2;
		   if(wei2==0) 
		   { EA=0;flag=1; i1++;if(i1==2)i1=0;
		   if(i1%2==0)
		   write(7,3);
		   if(i1%2==1)
		   write(7,5);}

		}
		xor1>>=1;
	    wei1=xor1%2;
	    if(wei1!=0)
		{
           temp_wei>>=3;
		   wei2=temp_wei%2;
		   if(wei2==0) 
		   { EA=1;flag=0; write(7,0);}

		}
	} 
   }
}
//  printf ("Temperature is '%d.%02d'\n", temp_int, temp_frac);
  }


// 将器件配置为使用外部 CMOS 时钟。
void sysclk_init (void)
{
  WDTCN = 0xde; // 禁止看门狗定时器
  WDTCN = 0xad;
  OSCXCN = 0x65; // 启动外部振荡器// 对于11.0592MHz的晶体,允许SYSCLK/1
  while ( (OSCXCN & XTLVLD_BIT) == 0 ){}// 等待外部振荡器起动
  OSCICN = 0x88; // 选择外部振荡器作为系统时钟// 禁止内部振荡器
}
 
// 配置交叉开关和 GPIO 端口
void xbar_init (void)
{
  XBR0 =0x00     ; // 允许SPI和 UART
  XBR1 = 0x00    ; //
  XBR2 = 0x40     ; // 允许交叉开关和弱上拉
//  PRT0CF |= 0x10; // 允许P0口的所有输出为弱上拉;// 让交叉开关将这些引脚配置为输入
  PRT1CF  |= 0xff;                     // P1.6 is push-pull
  PRT2CF  |= 0xff;                     // P1.6 is push-pull
  P1     |= 0xa0;   

}

// 配置 A/D 转换器使用定时器3溢出为转换启动源,并在转换完成时产生中断
void ADC_init (void)
{
  ADCEN = 0; // 禁止 ADC
  REF0CN =0x07      ; // 允许温度传感器,片内偏置发生器和偏置输出缓冲器
  AMX0SL = 0x0f     ; // 选择温度传感器为ADC多路开关的输出
  ADC0CF = 0x61    ; // ADC 转换时钟 = sysclk/8// 对11.0592MHz,GAIN = 2x
  ADC0CN =  0x45   ; // 禁止ADC,低功耗跟踪方式,// ADC 由定时器3溢出启动,数据左对齐
}

// 允许 ADC;定时器3溢出启动转换;允许ADC中断
void ADC_enable (void)
{                                                                                                                                                                                                                                                                                                                                                                                                                          
  ADCEN = 1       ; //允许 ADC
  EIE2 |=  0x02         ; //允许ADC中断(正常优先级)
}
//配置定时器1为 为补偿温度
void Timer0_Init(void)
{
   CKCON &= ~0x08;                     // Timer0 uses SYSCLK/12
   TMOD = 0x01;
   TCON = 0x10;                       // Enable Timer0 in Reload Mode
   TH0 = TIMER_RELOAD>>8;
   TL0 = TIMER_RELOAD;
   ET0 = 1;                            // Timer0 interrupt enabled
}

// 配置定时器3为自动重装载方式,定时间隔为 20ms(不产生中断)
void Timer3_init (void)
{
  TMR3CN = 0; // 停止定时器3,清除TF3,使用SYSCLK/12作为时基
  TMR3RLH = 0xff & ((-TC_20MS) >> 8);// 初始化重载值
  TMR3RLL = 0xff & (-TC_20MS);
  TMR3H = 0xff; // 立即重装载
  TMR3L = 0xff;
  EIE2 &=~0x01        ; // 禁止定时器3中断
  TMR3CN |= 0x04       ; // 启动定时器3
}

// ADC 转换结束 ISR
// 在此我们读 ADC 采样值,将其放入到16个采样值的缓冲区内,求所有采样值的平均值
// 并将其转换为以百分之一摄氏度为单位的温度值
void ADC_isr (void) interrupt 15
{ 
  int i; // 循环计数器
  long temp_temp; // 临时温度值
//ADC0CN=0xc5   ; // 清除ADC转换结束中断标志
ADCINT=0;
  temp_temp =  (ADC0H<<8)|ADC0L                  ; // 装入16位ADC结果
  temp[temp_ptr] = temp_temp; // 加到缓冲区中
  temp_ptr++;
  temp_ptr = temp_ptr % 16; // 回绕缓冲区指针
  temp_temp = 0L;
  for (i=0; i<16; i++) 
  {
    temp_temp = temp_temp + temp[i]; // 累加采样值,以便求均值
  }
  temp_temp =   temp_temp>>4          ; // 总和/16,求得平均值
// 至此,temp_temp 中为16个采样值得平均值。
//现在我们需要将其转换为以百分之一摄氏度表示的温度值。
//
// 在左对齐方式,ADC 产生的代码(CODE)与输入电压成正比:
// CODE = Vin * Gain / Vref * 2^16
//
// 温度传感器产生的电压(Vtemp)与以摄氏度表示的绝对温度(Temp)成正比:
// Vtemp = 2.86mV/C * Temp + 0.776V
//
// 结合这两个方程,我们可以将输出码(左对齐)与输入温度的关系表示为:
// CODE = (2.86mV/C * Temp + 0.776V) * Gain / Vref * 2^16
//
// 解上面的方程求Temp:
// CODE = 2.86mV/C * Temp * Gain/Vref * 2^16 + 0.776V * Gain/Vref * 2^16
// Temp =(CODE-(0.776V * Gain/Vref * 2^16))/(2.86mV/C * Gain/Vref * 2^16)
//
// 可以表示为:
// Temp = (CODE - K1) * K2
//
// 其中 K1 = 0.776 * Gain/Vref * 2^16
// K2 = 1/(2.86mV/C * Gain/Vref * 2^16)
//
// 对于 Vref = 2.4V 和 Gain = 2,
// K1 = 32,932 = 0xa58c
// K2 = 480 / 2^16 – 我们在所有计算中保持该值为480,在最后除以2^16。420=0x01a4
  temp_temp =   temp_temp-0xa58c                    ; // 将偏差校正到 0度, 0V
  temp_temp =    temp_temp*0x01a4                    ; // 2.5mV/摄氏度
  temp_temp = temp_temp * 100; // 显示结果,以百分之一摄氏度表示
  temperature = temp_temp >> 16; // 除以 2^16
//补写输出部分程序,将以百分之一度表示的温度值转换成两个十进制数,整数部分和小数部分

tem=(temperature-xz)/100;
write(2,tem/10);
write(1,tem%10);

if(max<tem&&max+2>tem) 
{write(0,14);
if(second%10!=0) write(8,1);
else if(second%10==0) write(8,0);}
else if(max+2<tem)
write(8,1);
else if(min>tem&&min-2<tem) 
{write(0,11);if(second%10!=0) write(8,1);
else if(second%10==0) write(8,0);}
else if(min<tem&&max>tem)
{write(8,0);write(0,15);}
else if(min-2>tem)
write(8,1);}
void write (int addr, int datain)
{
    char pp;
    PRT2CF  |= 0xff; 
    pp=addr;
	pp|= 0xA0;
	P1 =pp;
 
	P2=datain;
	wr=1;	
	wr=0;

}

unsigned int read()
{
   unsigned int data_rd;
   PRT2CF  &= 0xf0; 
   P2=0xff;
   rd=0;
   data_rd=P2;
   data_rd &=0x0f;

   rd=1;
   PRT2CF  |= 0xff; 

   return data_rd;

}

void delay(int time_10ms)
{

	for (n=0;n<=time_10ms;n++)
	{
		for(m=0;m<=10;m++)
		{
			for(l=0;l<=80;l++) ; 
		}
	}
}

//-------------------------------------------------------------------
// End Of File
//-------------------------------------------------------------------

⌨️ 快捷键说明

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