新手求助!C8051F020 单片机ADC串口 程序求助!

2019-07-15 21:06发布

为什么下位机向上位机发送的第一组数(共8字节)据缺失一个(第二字节),而且ADC并没有开始转换。从第二次开始正常。
#include <c8051f020.h>               
                  
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F02x
//-----------------------------------------------------------------------------
sfr16 ADC0     = 0xbe;                 // ADC0 data
sfr16 RCAP2    = 0xca;                 // Timer2 capture/reload
sfr16 RCAP3    = 0x92;                 // Timer3 capture/reload
sfr16 TMR2     = 0xcc;                 // Timer2
sfr16 TMR3     = 0x94;                 // Timer3
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
#define BAUDRATE     9600           // Baud rate of UART in bps
#define SYSCLK       22118400          // External crystal oscillator frequency
#define SAMPLE_RATE  50000             // Sample frequency in Hz
#define INT_DEC      256               // Integrate and decimate ratio
#define SAR_CLK      2500000           // Desired SAR clock speed
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void Resfresh_Watchingdog(void);
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 HC138Sel( unsigned char x );
void Uart_Send(void);
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
unsigned int AIN0[10],AIN1[10];
unsigned char Rec_Data[4],Send_Data[8]; //接收数组和发送数组
unsigned char Uart_flag,flag,DO,DI;
unsigned char num,ch; //采集数量和通道号
unsigned char address=0x01; //从机地址0x01
long Result0,Result1,Av_ADC0,Av_ADC1;
//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------
void main (void)
{
  // WDTCN = 0xde;                       // Disable watchdog timer
   //WDTCN = 0xad;
   OSCILLATOR_Init ();                 // Initialize oscillator
   PORT_Init ();                       // Initialize crossbar and GPIO
   UART0_Init ();                      // Initialize UART1
   TIMER3_Init (SYSCLK/SAMPLE_RATE);   // Initialize Timer3 to overflow at
                                       // sample rate
   ADC0_Init ();                       // Init ADC
   AD0EN = 1;                          // Enable ADC
   EA = 1;
ES0=1;                            // Enable global interrupts
   while (1)
   {   
    DI=P4;      //开关量输入读取
    Send_Data[0]=address; //放地址
  Send_Data[1]=DO;   
  Send_Data[2]=DI;
  Send_Data[3]= Av_ADC0>>8;//高四位放到数组
  Send_Data[4]= Av_ADC0;   //第八位放到数组
  Send_Data[5]= Av_ADC1>>8;//高四位放到数组
  Send_Data[6]= Av_ADC1;   //第八位放到数组

    Resfresh_Watchingdog();
  
     Uart_Send();
   //if(Uart_flag==0)
   //{
     Wait_MS (3000);  //延时程序
       // }
   

   
}
}


//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
   int i;                              // delay counter
   OSCXCN = 0x67;                      // start external oscillator with
                                       // 22.1184MHz crystal
   for (i=0; i < 256; i++) ;           // wait for oscillator to start
   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle
   OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                       // source and enable missing clock
                                       // detector
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.0   digital   push-pull     UART TX
// P0.1   digital   open-drain    UART RX
// P1.6   digital   push-pull     LED
// AIN0.1 analog                  Analog input (no configuration necessary)
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
   XBR0    = 0x04;                     // Route UART0 to crossbar
   XBR2    |= 0x40;                    // Enable crossbar,  weak pull-ups
   P0MDOUT |= 0x01;                    // enable TX0 as a push-pull output
P3MDOUT |= 0xff;        // enable LED as a push-pull output
  // P1MDOUT |= 0x40;                    // enable LED as push-pull output
HC138Sel( 4 );
   //P0MDOUT |= 0x01;                    // Set TX1 pin to push-pull
   //P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure the UART1 using Timer1, 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);     // set Timer1 reload value for baudrate
   TR1    = 1;                         // start Timer1
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base
   PCON  |= 0x80;                      // SMOD00 = 1
   TI0    = 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 disabled; normal tracking
                                       // mode; ADC0 conversions are initiated
                                       // on overflow of Timer3; ADC0 data is
                                       // right-justified
   REF0CN = 0x07;                      // Enable temp sensor, on-chip VREF,
                                       // and VREF output buffer
   AMX0CF = 0x00;                      // AIN inputs are single-ended (default)
   AMX0SL = 0x00;                      // Select AIN0.0 pin as ADC mux input
   ADC0CF = (SYSCLK/SAR_CLK) << 3;     // ADC conversion clock = 2.5MHz
   ADC0CF |= 0x00;                     // PGA gain = 1 (default)
   EIE2 |= 0x02;                       // enable ADC interrupts
}
//-----------------------------------------------------------------------------
// 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;                      // Stop Timer3; Clear TF3; set sysclk
                                       // as timebase
   RCAP3   = -counts;                  // Init reload values
   TMR3    = RCAP3;                    // Set to reload immediately
   EIE2   &= ~0x01;                    // Disable Timer3 interrupts
   TMR3CN |= 0x04;                     // start Timer3
}
//--------------------------------------------------------------------------------
//发送数据
//--------------------------------------------------------------------------------
void Uart_Send()  
{
  unsigned char i;
   for(i=0;i<8;i++)
     {
       SBUF0=Send_Data[i];
       while(!TI0);
       TI0=0;
   }
}
//-----------------------------------------------------------------------------
// 138译码器初始化
//-----------------------------------------------------------------------------
void HC138Sel( unsigned char x )    //138译码器选择通道
{
   P4 |= 0x07;
P4 &= ( x | 0xF8 );
}
//-----------------------------------------------------------------------------
// 看门狗刷新
//-----------------------------------------------------------------------------
void Resfresh_Watchingdog(void)    //138译码器选择通道
{
   WDTCN=0Xa5;
}
//-----------------------------------------------------------------------------
// 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;                            // Disable Timer 2 interrupts
   TR2 = 1;                            // Start Timer 2
   while(ms)
   {
      TF2 = 0;                         // Clear flag to initialize
      while(!TF2);                     // Wait until timer overflows
      ms--;                            // Decrement ms
   }
   TR2 = 0;                            // Stop Timer 2
}
void Uart0_Rec (void) interrupt 4
{
   unsigned  char  i;
    if(RI0)  //判断是接收终端还是发送终端??
   {  
     RI0=0;
     Rec_Data[i]=SBUF0;
   i++;
   
   }
   //TI0=0;
  if(i==4)
    {
    i=0;
    Uart_flag=1;
  }
  Resfresh_Watchingdog();
  if(Uart_flag==1)
  {
   //ES=0;
     if(Rec_Data[0]==address) //校验地址
      {
     
      DO=Rec_Data[1];  //控制开关量的输出
      P3=DO;
   // DI=P4;     //读取开关量的输入
    //Send_Data[0]=address;
    Send_Data[1]=DO;
   // Send_Data[2]=DI;
   // Send_Data[3]=Result>>8;
   // Send_Data[4]=Result;
      // Uart_Send(); //与延时程序配合使用,如果用延时程序,加词句可以将延时程序跳过,立即上传
   
       }
      Uart_flag=0;
              
   }
}
//-----------------------------------------------------------------------------
//ADC
//  两路采集 通道为AIN0.0和AIN0.1
//-----------------------------------------------------------------------------   
void ADC0_ISR (void) interrupt 15
{
  //unsigned char chanel;
  AD0INT = 0;     // Clear ADC conversion complete
   if(AMX0SL==0x00)  //  AIN0.0
     {
      AIN0[num]=ADC0;
     }
   if(AMX0SL==0x01)  //AIN0.1
     {
      AIN1[num]=ADC0;
     }
   ch++;
      switch(ch)      // 切换通道
      {
    case 1:
     AMX0SL=0x01;
      //chanel=0x01;
    break;
    case 2:
     AMX0SL=0x00;
    num++;    //计数
    ch=0;
    break;
    }
   /*if(ch==2)
     {
     ch=0;
   num++;
     }*/
   if(num==10)
   {
     flag=1;
     num=0;
   }
   Resfresh_Watchingdog();
  if(flag==1)
   {
      unsigned char i;
      for(i=0;i<10;i++)
       {
       Result0+=AIN0[i];
      
      Result1+=AIN1[i];
         
     }

      Av_ADC0=Result0/10*2430 / 4095;  //求ADC0平均值
       Result0=0;                     //清零
      Av_ADC1=Result1/10*2430 / 4095 ;  //求ADC1平均值
       Result1=0;                 //清零
   flag=0;
   }
   // AMX0SL=chanel;
  // AMX0SL=ch;
            
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。