📄 temp.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 + -