初级会员 
  
	- 积分
 - 126
 
        - 金钱
 - 126 
 
       - 注册时间
 - 2016-5-9
 
      - 在线时间
 - 12 小时
 
 
 
 | 
 
[mw_shl_code=c,true]#include <c8051f020.h>                 // SFR declarations 
#include <stdio.h>  
#include <intrins.h>  
#include "GPS.h"   
// 
// 特殊功能寄存器配置地址 
//----------------------------------------------------------------------------- 
sfr16 ADC0     = 0xbe;                 //16位SFR数据位地址为0xBE 
sfr16 RCAP2    = 0xca;                 //当定时器2被配置为捕捉方式时寄存器地址,RCAP2L寄存器捕捉定时器2的低字节。 
                                       //当定时器2被配置为自动重装方式时,它保存重载值的低字节。  
sfr16 RCAP3    = 0x92;                 //定时器3被配置为自动重装时寄存器地址,该寄存器保存重载值的低字节 
sfr16 TMR2     = 0xcc;                 //定时器2低字节地址 
sfr16 TMR3     = 0x94;                 //定时器3低字节地址 
 
sbit LED = P1^6;                       //LED='1' 亮灯 
sbit SW1 = P3^7;                       //SW1='0' 开关闭合 
 
//----------------------------------------------------------------------------- 
// 定义全局变量 
//----------------------------------------------------------------------------- 
#define BAUDRATE     115200            // 设置UART波特率 
#define SYSCLK       22118400          // 外部晶振频率,开发板上的晶振 
#define SAMPLE_RATE  50000             // 设置ADC0的采样率Hz。依据ADC0转换速率最高100ksps,因此最大采样率为100 000hz设置. 
#define INT_DEC      256               // 过采样取平均值的次数。由过采样去平均值可提高ADC0的分辨率 
#define SAR_CLK      2500000           // 理想的SAR时钟速度 
#define SAMPLE_DELAY 50                // 采样延时50ms 
#define ANALOG_INPUTS 2                // 两路输入管脚AIN0.0,AIN0.1  
 
//----------------------------------------------------------------------------- 
// 函数原型 
//----------------------------------------------------------------------------- 
 
void OSCILLATOR_Init (void);            
void PORT_Init (void); 
void UART0_Init (void); 
void ADC0_Init (void); 
void TIMER3_Init (void); 
 
void ADC0_ISR (void); 
void TIMER2_ISR (void); 
void Uart_Receive(void); 
void Wait_MS (unsigned int ms); 
//----------------------------------------------------------------------------- 
// 全局变量 
//----------------------------------------------------------------------------- 
long Result[ANALOG_INPUTS];            // ADC0 decimated value,模拟输入 
unsigned char amux_input=0;            // 多路模拟复用输入 
unsigned char amux_convert=0; 
unsigned char flag_data;        //数据标志位 
 
char   xdata rev_buf[80];        //接收缓存              
uchar  xdata rev_start = 0;     //接收开始标志       
uchar  xdata rev_stop  = 0;     //接收停止标志      
uchar  xdata gps_flag = 0;      //GPS处理标志       
uchar  xdata num = 0;           // 
char   xdata buf[80];        //接收缓存              
 
 
//----------------------------------------------------------------------------- 
//    子程序初始化 
//----------------------------------------------------------------------------- 
//     晶振初始化 
//----------------------------------------------------------------------------- 
// 
// 返回值 : 无 
// 参数   : 无 
// 初始化使用22.1184MHz的晶振作为时钟源 
//----------------------------------------------------------------------------- 
void OSCILLATOR_Init (void) 
{ 
   int i;                              // 延时计数变量 
 
   OSCXCN = 0x67;                      // 启动外部晶振22.1184MHz 
 
   for (i=0; i < 256; i++) ;           // 等待晶振启动 
 
   while (!(OSCXCN & 0x80)) ;          // 检测晶振是否正常工作,若开始工作执行下面的程序 
 
   OSCICN = 0x88;                      // 选择外部晶振作为时钟源,使能打开时钟检测位 
 
} 
//-----------------------------------------------------------------------------                                                                                 
//----------------------------------------------------------------------------- 
// 端口初始化 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// 返回值 : 无 
// 参数   : 无 
// 
// 本函数用于配置crossbar和GPIO端口. 
// P0.0   数字推挽方式        UART TX 
// P0.1   数字   漏极开关     UART RX 
// P1.6   数字   推挽方式     LED 
// AIN0.1 模拟输入  (无配置需要) 
 
//----------------------------------------------------------------------------- 
void PORT_Init (void) 
{ 
   XBR0    = 0x04;                     // Route UART0 to crossbar 
   XBR2    |= 0x40;                    // 使能交叉开关,弱上电 
   P0MDOUT |= 0x01;                    // 允许TX0作为推挽式输出 
   P1MDOUT |= 0x40;                    // 允许LED作为推挽式输出 
 
   P0MDOUT |= 0x01;                    // 设置TX1管脚为推挽式 
   P1MDOUT |= 0x40;                    // 设置LED(P1^6)为推挽式 
} 
 
//----------------------------------------------------------------------------- 
// 串口初始化 
//----------------------------------------------------------------------------- 
// 
// 返回值 : 无 
// 参数   : 无 
// 
//使用定时器1配置UART0端口,串口其他设置为8——N——1 
// 
//----------------------------------------------------------------------------- 
void UART0_Init (void) 
{ 
   SCON0   = 0x50;                     // SCON0: 模式 1, 8-bit UART, enable RX 
   TMOD    = 0x20;                     // TMOD: timer 1, mode 2, 8-bit reload 
   TH1    = -(SYSCLK/BAUDRATE/16);     // set Timer1 reload value for baudrate 
   TR1    = 1;                         // start Timer1 
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base 
   PCON  |= 0x80;                      // SMOD00 = 1 
   TI0    = 1;                         // 发送中断标志位 
 
  
} 
 
//----------------------------------------------------------------------------- 
// ADC0_Init 
//----------------------------------------------------------------------------- 
// 
// 返回值 : 无 
// 参数   : 无 
// 
// 定时器3溢出标志着转换的完成,右对齐输出模式。使能ADC结束转换中断,关闭ADC 
// 
//----------------------------------------------------------------------------- 
void ADC0_Init (void) 
  { 
 
   ADC0CN =0x04;                      // ADC0不工作;正常追踪保持模式; ADC0转换初始化右对齐 
                                         
   REF0CN = 0x07;                      // 温度传感器打开, 内部电压基准缓冲器工作。内部电压基准提供从 VREF 引脚输出 
                                        
   AMX0CF = 0x00;                      // AIN单端输入 
   AMX0SL = 0x00;                      // 选择AIN0.1管脚作为ADC mux的输入通道,ISR随着输入量发生改变  
  
                        
   ADC0CF = (SYSCLK/SAR_CLK) << 3;     // ADC转换时钟2.5MHz 
   ADC0CF |= 0x00;                     // PGA gain = 1 (default) 
 
   EIE2 |= 0x02;                       // ADC0转换结束中断 
 
  } 
 
 
//----------------------------------------------------------------------------- 
// TIMER3_Init 
//----------------------------------------------------------------------------- 
// 
// Return Value : None 
// Parameters   : 
//   1)  none 
// 
// Configure Timer3 to auto-reload at interval specified by <counts> (no 
// interrupt generated) using SYSCLK as its time base. 
// 
//----------------------------------------------------------------------------- 
void TIMER3_Init (void) 
{ 
 
   TMR3CN = 0x02;                      // Stop Timer3; Clear TF3; set sysclk 
                                       // as timebase 
 
   RCAP3   = 65535 -(SYSCLK / 50000);  // Init reload values for 20uS 
   TMR3    = RCAP3;                    // Set to reload immediately 
   EIE2   |= 0x01;                    // Disable Timer3 interrupts 
   TMR3CN |= 0x04;                     // start Timer3 
 
} 
//主函数 
void main (void) 
{ 
   int hour,min,sec; 
   unsigned char i; 
   long measurement;                   // 电压单位是mV 
   //int Pressure;             //压力单位是Mpa 
   WDTCN = 0xde;                       // 关闭看门狗定时器 
   WDTCN = 0xad; 
 
   OSCILLATOR_Init ();                 // 初始化晶振 
   PORT_Init ();                       // 初始化crossbar和GPIO 
   UART0_Init ();                      // 初始化UART0 
   TIMER3_Init ();                     // 初始化定时器3溢出时间为1ms 
   ADC0_Init ();                       // ADC初始化 
 
   AD0EN = 1;                          // 打开ADC 
   EA = 1;                             // 允许全局中断 
 
   while (1) 
   { 
      EA = 0;                          // 关闭中断 
 
        if((rev_stop==1)&&(buf[5]=='C'))//如果接收到GPS模块的GPRMC数据 
        {   
            ES=0; 
           hour= (buf [7]-0x30)* 16+ buf[8] -0x30; 
           min=  (buf [9]-0x30)* 16+ buf[10]-0x30; 
           sec=  (buf[11]-0x30)* 16+ buf[12]-0x30; 
         
           hour=  hour / 16 * 10 + hour % 16; 
           hour= (hour+8) % 24;//UTC Time换算成北京时间 
           hour=hour/10*16+hour%10; 
 
           ES=1; 
           rev_stop=0; 
        } 
       for(i=0; i<2; i++) 
            { 
           // 12-bit的 ADC通过INT_DEC求平均得到电压值.   
          // 结果存储在Result中,右对齐  
         // 通过AIN 0.1口的电压计算方法式子: 
         //                           Vref (mV) 
         //   measurement (mV) =   --------------- * Result (bits)  
         //                       (2^12)-1 (bits) 
                 
         measurement =  Result * 2430 / 4095; 
                // Pressure=measurement*2.4/2.5/1000; 
             } 
                         printf("shijian: %bu,AIN0.%bu voltage: %ld\tmv\n",hour,i,measurement); 
      EA = 1;                          // 重启中断 
      Wait_MS(SAMPLE_DELAY);           // 等待下一次采样 
   } 
} 
 
//----------------------------------------------------------------------------- 
// 中断服务程序 
//----------------------------------------------------------------------------- 
 
//----------------------------------------------------------------------------- 
// ADC0_ISR 
//----------------------------------------------------------------------------- 
// 
// This ISR is called when the ADC0 completes a conversion.  Each value is  
// added to a running total <accumulator>, and the local decimation counter  
// <int_dec> decremented. When <int_dec> reaches zero, we post the decimated 
// result in the global variable <Result[]>. 
// 
// The analog input is sampled, held, and converted on a Timer2 overflow.  To 
// maximize input settling time, the analog mux is also advanced to the next 
// input on the Timer2 overflow.  Two different indices are held globally: 
//    amux_convert:  index of the analog input undergoing conversion 
//    amux_input:    index of the analog input selected in the analog  
//                   multiplexer 
//  
// 
//----------------------------------------------------------------------------- 
void ADC0_ISR (void) interrupt 15 
{ 
 
   static unsigned int_dec=INT_DEC;    // Integrate/decimate counter 
                                       // we post a new result when 
                                       // int_dec = 0 
 
   static long accumulator[ANALOG_INPUTS] ={0L};        
                                       // Here's where we integrate the 
                                       // ADC samples from input AIN0.0 
   unsigned char i; 
 
   AD0INT = 0;                         //clear ADC conversion complete overflow 
 
   accumulator[amux_convert] += ADC0;  // Read ADC value and add to running 
                                       // total 
 
   if(amux_convert == (ANALOG_INPUTS-1))// reset input index if the last input  
                                       //was just read 
      { 
      int_dec--;                       // Update decimation counter 
                                       // when last of the analog inputs  
                                       // sampled 
      } 
 
   if (int_dec == 0)                   // If zero, then post result 
   { 
      int_dec = INT_DEC;               // Reset counter 
 
      for(i=0; i<ANALOG_INPUTS; i++) 
         { 
            Result = accumulator >> 8; //Copy decimated values into Result  
            accumulator = 0L;          // Reset accumulators 
         } 
   } 
 
      amux_convert = amux_input;          // now that conversion results are  
                                       // stored, advance index to the analog 
                                       // input currently selected on the mux 
 
      LED = 1; 
 
} 
 
//----------------------------------------------------------------------------- 
// TIMER2_ISR 
//----------------------------------------------------------------------------- 
// 
// The timer2 overflow triggers the ADC0 conversion on the analog MUX input 
// previously selected.  It is permissable to change the analog MUX 
// input once conversion has started, as the ADC has an internal sample  
// and hold. 
// 
// This ISR routine will then select the next analog MUX input so as to  
// maximize the settling time. 
// 
//----------------------------------------------------------------------------- 
 
void TIMER2_ISR(void) interrupt 14 
{ 
 
       TMR3CN &= ~0x80;                    // 中断应答 
 
       amux_input ++;                      // 转向另一路模拟输入 
  
    if(amux_input == ANALOG_INPUTS)     // 若读取到最后一位输入,则重新设置输入参数  
      {                                 
         amux_input=0;                    // 将输入重新设置为AIN0.0开始 
      } 
 
       AMX0SL = amux_input;                // 为模拟复用选择下一个输入 
    
       LED = 0;                         
} 
 
 
/***************************************************************/ 
/*************************单片机串口数据接收**************************/ 
/***************************************************************/ 
void Uart_Receive(void) interrupt 4 
{ 
          unsigned char ch,num; 
          ES = 0; 
 
         if (RI)//如果接收完成则进入 
           { 
            ch=SBUF; 
           if (ch == '$')  //如果收到字符'$',便开始接收 
              { 
               rev_start = 1; 
               rev_stop  = 0;  //接收停止标志 
              } 
 
          if (rev_start == 1)       //标志位为1,开始接收 
             { 
           buf[num++] = ch;  //字符存到数组中 
               if (ch == '\n')       //如果接收到换行 
                 { 
                 buf[num] = '\n'; 
                rev_start = 0; 
                rev_stop  = 1;  //接收停止标志 
                 num = 0; 
                 } 
              } 
            } 
             RI = 0; //RI清0,重新接收 
             ES = 1; //串口1中断允许 
}  
 
//----------------------------------------------------------------------------- 
// 延时子程序 
//----------------------------------------------------------------------------- 
// 
// Return Value : 无 
// Parameters: 
//   1) unsigned int ms - number of milliseconds of delay 
//                        range is full range of integer: 0 to 65335 
// 
// 本程序引入一个毫秒级的延时. 
// 
//----------------------------------------------------------------------------- 
void Wait_MS(unsigned int ms) 
{ 
 
   CKCON &= ~0x20;                     // use SYSCLK/12 as timebase 
 
   RCAP2 = -(SYSCLK/1000/12);          // Timer 2 overflows at 1 kHz 
   TMR2 = RCAP2; 
 
   ET2 = 0;                            // 禁止定时器2中断 
 
   TR2 = 1;                            // 打开定时器2 
 
   while(ms) 
   { 
      TF2 = 0;                         // 清除标志位初始化 
      while(!TF2);                     // 等待定时器溢出 
      ms--;                            // 时间减少 
   } 
 
   TR2 = 0;                            // 关闭定时器2 
}[/mw_shl_code] 
 |   
 
 
 
 |