初级会员 
  
	- 积分
 - 126
 
        - 金钱
 - 126 
 
       - 注册时间
 - 2016-5-9
 
      - 在线时间
 - 12 小时
 
 
 
 | 
 
1金钱 
 本帖最后由 cjf1018 于 2016-7-5 11:30 编辑  
 
怎么添加一个流量测量的代码?[mw_shl_code=c,true]//程序测量电压在外部ADC输入并打印,结果通过UART终端串口读出。  
#include <c8051f020.h>                 // 特殊寄存器的声明 
#include <stdio.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' 开关闭合 
long Result;                           //定义变量类型为long型 
//----------------------------------------------------------------------------- 
// 定义全局变量 
//----------------------------------------------------------------------------- 
#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 
 
//----------------------------------------------------------------------------- 
// 函数原型 
//----------------------------------------------------------------------------- 
void OSCILLATOR_Init (void);            
void PORT_Init (void); 
void UART0_Init (void); 
void ADC0_Init (void); 
void TIMER3_Init (int counts); 
void ADC0_ISR (void); 
void Wait_MS (unsigned int ms); 
 
//----------------------------------------------------------------------------- 
// 主函数 
//----------------------------------------------------------------------------- 
void main (void) 
{ 
   long measurement;                   // 测量电压的单位mv 
 
   WDTCN = 0xde;                       // 关闭看门狗 
   WDTCN = 0xad; 
   //初始化函数 
   OSCILLATOR_Init ();                  
   PORT_Init ();                      
   UART0_Init ();                       
   TIMER3_Init (SYSCLK/SAMPLE_RATE);            
   ADC0_Init ();                        
 
   AD0EN = 1;                          // 打开ADC 
   EA = 1;                             // 允许中断 
   while (1) 
   { 
      EA = 0;                          // 禁止中断 
 
      // 12-bit的 ADC通过INT_DEC求平均得到电压值.   
      // 结果存储在Result中,右对齐  
      // 通过AIN 0.1口的电压计算方法式子: 
      //                           Vref (mV) 
      //   measurement (mV) =   --------------- * Result (bits)  
      //                       (2^12)-1 (bits) 
 
      measurement =  Result * 2430 / 4095; //电压计算结果 
      EA = 1;                          // 重启中断 
      printf("AIN0.1 voltage: %ld mV\n",measurement);//Keil内部函数printf打印输出电压值 
      LED = ~SW1;                      // LED等的亮灭也反映了开关的情况 
      Wait_MS(SAMPLE_DELAY);           // 等待50ms下一次采样 
   } 
} 
//----------------------------------------------------------------------------- 
// 子程序初始化 
//----------------------------------------------------------------------------- 
   // 晶振初始化 
//----------------------------------------------------------------------------- 
// 返回值 : None 
// 参数   : None 
// 初始化使用22.1184MHz晶振作为时钟源 
void OSCILLATOR_Init (void) 
{ 
   int i;                              // 定义延时计数变量 i 
   OSCXCN = 0x67;                      // 启动外部晶振22.1184MHz 
   for (i=0; i < 256; i++) ;           // 等待晶振启动 
          while (!(OSCXCN & 0x80)) ;       // 检测晶振是否在运行,若正常工作则开始执行下面的程序 
           OSCICN = 0x88;                  // 将外部晶振作为系统时钟,使能打开时钟丢失检测位。 
} 
//----------------------------------------------------------------------------- 
// 端口初始化 
//----------------------------------------------------------------------------- 
// 返回值 : None 
// 参数   : None 
// 
// 本函数用于配置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;                    // 设置P1.6(LED)为推挽式 
 
} 
 
//----------------------------------------------------------------------------- 
// UART0_Init 
//----------------------------------------------------------------------------- 
// 返回值 : None 
// 参数   : None 
// 
// 使用定时器1配置UART1.for <baudrate> and 8-N-1. 
//----------------------------------------------------------------------------- 
void UART0_Init (void) 
{ 
   SCON0  = 0x50;                     // SCON0: mode 1, 8-bit UART, enable RX 
   TMOD   = 0x20;                     // TMOD: timer 1, mode 2, 8-bit reload 
   TH1    = -(SYSCLK/BAUDRATE/16);     // 计数寄存器赋初值 
   TR1    = 1;                         // 启动定时器1 
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base 
   PCON  |= 0x80;                      // SMOD00 = 1,波特率发生器,波特率加倍 
   TI0    = 1;                         // Indicate TX0 ready 
} 
void UART1_Init (void) 
{ 
   SCON1  = 0x50;                     // SCON0: mode 1, 8-bit UART, enable RX 
   TMOD   = 0x20;                     // TMOD: timer 1, mode 2, 8-bit reload 
   TH1    = -(SYSCLK/BAUDRATE/16);     // 计数寄存器赋初值 
   TR1    = 1;                         // 启动定时器1 
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base 
   PCON  |= 0x80;                      // SMOD00 = 1,波特率发生器,波特率加倍 
   TI1    = 1;                         // Indicate TX0 ready 
} 
 
//----------------------------------------------------------------------------- 
// ADC0_Init 
//----------------------------------------------------------------------------- 
// 
// Return Value : None 
// Parameters   : None 
// 
// Configure ADC0 to use Timer3 overflows as conversion source, to 
// generate an interrupt on conversion complete, and to use right-justified 
// output mode.  Enables ADC end of conversion interrupt. Leaves ADC disabled. 
// 
//----------------------------------------------------------------------------- 
void ADC0_Init (void) 
{ 
 
   ADC0CN = 0x04;                      // ADC0禁止,正常追踪模式,定时器3溢出时启动ADC0,ADC0寄存器数据右对齐 
 
  // REF0CN = 0x07;                      // Enable temp sensor, on-chip VREF, 
                                       // and VREF output buffer 
 
   AMX0CF = 0x00;                      // AIN输入为单端输入 (默认情况下) 
 
   AMX0SL = 0x01;                      // 选择AIN0.1引脚作为ADC mux输入 
 
   ADC0CF = (SYSCLK/SAR_CLK) << 3;     // ADC转换时钟= 2.5MHz 
   ADC0CF |= 0x00;                     // ADC0内部放大器增益PGA gain = 1 (默认) 
 
   EIE2 |= 0x02;                       // 打开ADC中断,允许ADC0转换结束产生中断请求 
} 
 
//----------------------------------------------------------------------------- 
// TIMER3_Init 
//----------------------------------------------------------------------------- 
// 
// Return Value : None 
// Parameters   : 
//   1)  int counts - calculated Timer overflow rate 
//                    range is postive range of integer: 0 to 32767 
// 
// Configure Timer3 to auto-reload at interval specified by <counts> (no 
// interrupt generated) using SYSCLK as its time base. 
// 
//----------------------------------------------------------------------------- 
void TIMER3_Init (int counts) 
{ 
 
   TMR3CN = 0x02;                      // 停止定时器3;清零TF3溢出标志位;将系统时钟作为时间基准 
   RCAP3   = -counts;                  // 初始化重载值 
   TMR3    = RCAP3;                    // 设置立即自动重载 
   EIE2   &= ~0x01;                    // 禁止中断 
   TMR3CN |= 0x04;                     //启动定时器 
 
} 
 
//----------------------------------------------------------------------------- 
// 中断服务程序 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
// ADC0_ISR 
//----------------------------------------------------------------------------- 
// Here we take the ADC0 sample, add it to a running total <accumulator>, and 
// decrement our local decimation counter <int_dec>.  When <int_dec> reaches 
// zero, we post the decimated result in the global variable <Result>. 
// 
//----------------------------------------------------------------------------- 
void ADC0_ISR (void) interrupt 15         //x*8+3=中断向量地址0x7B 
{ 
   static unsigned int_dec=INT_DEC;    // Integrate/decimate counter 
                                       // we post a new result when 
                                       // int_dec = 0 
   static long accumulator=0L;         // Here's where we integrate the 
                                       // ADC samples 
    AD0INT = 0;                         // Clear ADC conversion complete 
                                       // indicator 
   accumulator += ADC0;                // 读取ADC数值并累加结果 
   int_dec--;                          // 更新int_dec数值,减1 
 
   if (int_dec == 0)                   // 若int_dec为0,则输出结果 
   { 
      int_dec = INT_DEC;               // 重新设置计数器 
      Result = accumulator >> 8; 
      accumulator = 0L;                // 重新设置累加器 
   } 
} 
 
//----------------------------------------------------------------------------- 
// Support Subroutines 
//----------------------------------------------------------------------------- 
 
//----------------------------------------------------------------------------- 
// Wait_MS 
//----------------------------------------------------------------------------- 
// 
// Return Value : None 
// Parameters: 
//   1) unsigned int ms - number of milliseconds of delay 
//                        range is full range of integer: 0 to 65335 
// 
// This routine inserts a delay of <ms> milliseconds. 
// 
//----------------------------------------------------------------------------- 
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;                            // Stop Timer 2 
} 
//----------------------------------------------------------------------------- 
// End Of File 
//-----------------------------------------------------------------------------[/mw_shl_code] |   
 
 
最佳答案
查看完整内容[请看2#楼] 
要求不高的话,先读电流通道,再读电压通道就可以了。开2个通道。
要求高,就要2个ADC,同时采集(保证电流电压同时擦剂)。然后依次读取。 
 
 
 
 
 
 
 |