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

📄 temperature.c

📁 BTF330实验程序。针对c8051f330的大部分外设的实验程序
💻 C
字号:
/*----------------------------------------------------------------------------
拔下短路环J8,连上短路环 J10,J12和J21。
功能:在LCD上显示从内部温度传感器传来的温度值.

------------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <c8051f330.h>                 
#include <stdio.h>

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F33x
//-----------------------------------------------------------------------------

sfr16 TMR2RL   = 0xca;                 // 定时器2重装载寄存器
sfr16 TMR2     = 0xcc;                 // 定时器2计数寄存器
sfr16 ADC0     = 0xbd;                 // ADC 数据寄存器

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define SYSCLK      24500000           // 系统时钟频率          
#define BAUDRATE        9600           // UART的波特率
#define TIMER2_RATE     1000           // 定时器2溢出率


//sbit LED = P1^0;                       // LED='1' 为开
//-----------------------------------------------------------------------------
// Temperature Sensor Calibration PARAMETERS
//-----------------------------------------------------------------------------
#define AMB_TEMP           22         // Ambient Calibration Temperature 
                                       // (degC)此校准值取决于运行程序时的环境温度

#define TEMP_SENSOR_GAIN   2860        // Temp Sensor Gain in (uV / degC)

#define VREF               3300        // ADC 参考电压 (mV)

#define SOAK_TIME          15          // Soak Time in Seconds


//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------

// 在FLASH存储空间分配2字节
// 用来存储温度校准值
unsigned int code TEMP_OFFSET = 0xFFFF;

//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

void SYSCLK_Init (void);
void ADC0_Init (void);
void UART0_Init (void);
void PORTa_Init (void);
void Timer2_Init (int);
void Write_COM(unsigned yjcom );
void Write_CHAR(unsigned char yjchar);
void YJ_Init(void);
int get_temp (void);
void calibrate(void);
unsigned int measure(void);
void wait_one_second (void);
unsigned int m1,m2,m3,m4;
  unsigned char aa,bb,cc,dd; 
unsigned char xdata tab2[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
int k;
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void main (void) {

   unsigned temperature;
 unsigned int i; 
                                        
   PCA0MD &= ~0x40;                     // 禁止看门狗
   PORTa_Init();                        // 端口初始化
   SYSCLK_Init ();                     // 系统时钟

   ADC0_Init ();                       //  初始化
   Timer2_Init(SYSCLK/TIMER2_RATE);    // 定时器2初始化
   UART0_Init();

   AD0EN = 1;                          // 使能ADC0

   if (TEMP_OFFSET == 0xFFFF) {        // TRUE if first-time to execute
     printf ("Calibrating...\n");
      calibrate ();                    // execute calibration sequence
   } else {
     printf ("Not calibrating.\n");
   }

   while (1) {
     
      temperature = get_temp ();
     printf ("Temperature = %+02d hundredths degrees C\n", temperature);
	  m1=temperature/1000;
	  m2=(temperature-1000*m1)/100;
      m3=(temperature-1000*m1-100*m2)/10;
	  m4=temperature-1000*m1-100*m2-10*m3;
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
i=0;
do
{;
 if(i==m1)aa=tab2[i];
      
 if(i==m2) bb=tab2[i];
     
 if(i==m3) cc=tab2[i];
      
 if(i==m4) dd=tab2[i];
 i++;
       
}while(i<10);

    YJ_Init();
	for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
    for(k=0;k<4000;k++);
 	Write_CHAR(aa);
 	Write_CHAR(bb);
	Write_CHAR(0x2e);
	Write_CHAR(cc);
	Write_CHAR(dd);
	Write_CHAR(0xdf);
	Write_CHAR(0x43);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
     for(k=0;k<4000;k++);
   }
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// 配置交叉开关和所用端口.
//
// P0.4 - UART TX
// P0.5 - UART RX
// P1.0 - LED

void PORTa_Init (void)
{
  
   P0MDOUT |= 0x10;                    //使能TX为推挽输出
  
   XBR0    = 0x01;                     // 使能UART P0.4(TX) and P0.5(RX)                     
   XBR1    = 0x40;                     // 使能交叉开关和弱上拉
}

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
//

void SYSCLK_Init (void)
{
   OSCICN |= 0x03;                     // 配置为内部晶振
                                       // 
   RSTSRC  = 0x04;                     // 使能时钟丢失检测

}

//-----------------------------------------------------------------------------
// ADC0_Init ADBUSY, LP tracking, no Interrupt, ADC disabled
//-----------------------------------------------------------------------------
//
// 配置 ADC0 的 ADBUSY为作为开始转换标志,  
//   禁止ADC转换完进入中断.
// 
void ADC0_Init (void)
{
   ADC0CN = 0x40;                      // ADC0 禁止; LP tracking
                                       // mode; ADC0 conversions are initiated 
                                       // on a write to ADBusy
   AMX0P  = 0x10;                      // 温度传感器的输出作为正端输入
 
   AMX0N  = 0x11;                      // 单端模式

   ADC0CF = (SYSCLK/3000000) << 3;     // ADC 转换时钟为 3MHz   

   ADC0CF &= ~0x04;                    // 使 ADC0 右对齐
   REF0CN = 0x0e;                      // 使能温度传感器, VREF = VDD, 偏置电压产生
                                       
   EIE1 &= ~0x08;                      // 禁止ADC 中断
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// 用定时器配置UART0.
//
void UART0_Init (void)
{
   SCON0 = 0x10;                      
   if (SYSCLK/BAUDRATE/2/256 < 1) {
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } else if (SYSCLK/BAUDRATE/2/256 < 4) {
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01                  
      CKCON |=  0x09;
   } else if (SYSCLK/BAUDRATE/2/256 < 12) {
      TH1 = -(SYSCLK/BAUDRATE/2/12);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }

   TL1 = TH1;                          // init Timer1
   TMOD &= ~0xf0;                      // TMOD: 定时器1,8位自动重装载
   TMOD |=  0x20;                       
   TR1 = 1;                            // 启动定时器1
   TI0 = 1;                            // 指示 TX0准备好
}

//-----------------------------------------------------------------------------
// Timer2_Init SYSCLK no Interrupt
//-----------------------------------------------------------------------------
//
// 配置 Timer2自动重装载,从装载值为 <counts> (不产生中断).
//使用系统时钟作为时间基准.
void Timer2_Init (int counts)
{
   TMR2CN = 0x00;                      // 禁止Timer2; 清 TF2H and TF2L;
                                       // 禁止低字节中断产生
                                       // 分离模式; 选择内部时间基准
   CKCON |= 0x10;                      // Timer2 用系统时钟作为基准

   TMR2RL  = -counts;                  // 初始化定时器2重装载值
   TMR2    = TMR2RL;                  
   ET2 = 0;                            // 禁止定时器2中断
   TR2 = 1;                            // 启动定时器2
}

//-----------------------------------------------------------------------------

// wait_soak_time
//-----------------------------------------------------------------------------
//
// 这段程序用来延时一定时间等待输出稳定结果.
// 
void wait_soak_time (unsigned char soak_time)
{
   unsigned char i;

   for( i = soak_time; i != 0; i--) {
      wait_one_second();
      printf ("Soaking...%d\n", (int) i);
   }
}
  
//-----------------------------------------------------------------------------
// 延时1秒
//-----------------------------------------------------------------------------

void wait_one_second (void)
{
   unsigned int count;
   TF2H = 0;                           // 清定时器2溢出标志
   TR2 = 1;                            // 启动定时器2
   
   for (count = TIMER2_RATE; count != 0; count--) {
      while (!TF2H);                   // 等待溢出
      TF2H = 0;                        // 清溢出标志
   }

   TR2 = 0;                            // 定时器2禁止
}

//-----------------------------------------------------------------------------
// calibrate
//-----------------------------------------------------------------------------
//
void calibrate (void)
{

   bit EA_state=EA;                    // 保存EA状态
   unsigned char xdata * codePtr;      // 用于在FLASH存储空间写校准值
                                       
   unsigned int code* data pread;      // 读FLASH指针

   long temp_offset;                   // 存储ADC的返回值
   pread = (unsigned int code *) TEMP_OFFSET;

   wait_soak_time(SOAK_TIME);          // 等待使温度稳定
   temp_offset= (long) measure ();     // 读取ADC过采样代码

   // now calculate the 0 DEG C offset value using <temp_offset>, the
   // temp sensor gain (TEMP_SENSOR_GAIN), and the ambient temperature.

   temp_offset = temp_offset - ((long) AMB_TEMP * 
                 TEMP_SENSOR_GAIN / VREF * 65536 / 1000);
   
   codePtr=(unsigned char xdata*) &TEMP_OFFSET;               
                                       // 指向 TEMP_OFFSET

   EA = 0;                             //总的中断禁止


   FLKEY=0xA5;                         // 输入第一个关键代码
   FLKEY=0xF1;                         //输入第二个关键代码
                                       // FLASH 现在没有被锁定
 
   PSCTL |= 0x01;                      //  FLASH 写使能
   *codePtr = (temp_offset>>8);        // 写temp_offset的高8位值
   PSCTL &= ~0x01;                     //  FLASH 写禁止

   codePtr++;                          // Move to low byte of
                                       // 移动地址指针用来
                                       //存储采样值的低字节
 
   FLKEY=0xA5;                         // 输入第一个关键代码
   FLKEY=0xF1;                         // 输入第二个关键代码
                                       //  FLASH 现在没有被锁定
 
   PSCTL |= 0x01;                      // FLASH 写使能

   *codePtr =temp_offset;              //写temp_offset的低8位值
     
      
   PSCTL = 0x00;                       //  FLASH 写禁止
   EA = EA_state;                      // 恢复EA状态

}

//-----------------------------------------------------------------------------
// measure
//-----------------------------------------------------------------------------
//
// 本程序通常进行 16383 ADC采样并且返回16位无符号结果
 
unsigned int measure (void)
{
   unsigned i;                         // 采样计数器
   unsigned long accumulator=0L;       // ADC采样值的总和
                                      
   unsigned int currval;

   AD0INT = 0;
   AD0BUSY = 1;

   // 读ADC值进行累加
   i = 0;
   do 
   {
      while (!AD0INT);                 // 等待转换完成
      AD0INT = 0;                      // 清转换中断标志

      currval=ADC0;                    // 存储最终ADC转换值          
      AD0BUSY = 1;                     // 启动ADC转换
      accumulator += currval;          // 累加
      i++;                             // 更新记数值
   } while (i != 16383);
   return (unsigned int) (accumulator >> 8);
   // 转换到获取16位的结果 (14 + 10 = 24 - 8 = 16) bits
}


int get_temp (void)
{
   unsigned int ADC_code;
   long result;
   
   ADC_code = measure();
   
   result = ADC_code - TEMP_OFFSET;

   result = result * (long) VREF / 256 * 1000 / TEMP_SENSOR_GAIN * 100 / 256;
   
   return (int) result;
}

⌨️ 快捷键说明

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