×
单片机 > 单片机程序设计 > 详情

C8051F020 AD转换和USB通信

发布时间:2020-06-04 发布时间:
|

config.c

 

#include "include.h"

// Peripheral specific initialization functions,
// Called from the Init_Device() function

void Timer0_Init (void)
{
    TMOD      = 0x01; 
    TH0       = TH0_VALUE;
 TL0       = TL0_VALUE;
  
}

void ADC_Init()
{
    AMX1SL    = 0x00;   //
    ADC1CF    = 0x21;   //
    ADC1CN    = 0x80;   //
    REF0CN    = 0x03;
}

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

void PORT_Reset(void)
{
   // disable watchdog timer
    // disable watchdog timer
   WDTCN = 0xde;
   WDTCN = 0xad;

   //P0MDOUT|=0x10;
   XBR0 = 0x04;  // CP0E    ECI0E   PCA0ME PCA0ME PCA0ME [UART0]  SPI0EN [SMB0EN]
 
   XBR1 = 0x14;  // SYSCKE  T2EXE   T2E    INT1E  T1E    [INT0E]  T0E    CP1E
  
   XBR2 = 0x40;  // WEAKPUD [XBARE] -      T4EXE  T4E    [UART1E] EMIFLE CNVSTE
                 
   P0MDOUT|=0x0;
   P1MDIN=0x0;  //Digital Input Mode  
   //P1MDOUT=0x0f; //Key Input Drain-out    
   //P1=0xff;   //Key Input

   //P2MDOUT=0x00; //CH372 WR RD CS A0 Output   
   P2MDOUT=0xff;
   //P2=0xff;
   P2=0xff;

   P3MDOUT=0x00; //input   
   P3=0xff;
  
   P74OUT=0;      //P7 CH372 data  
   P7=0xff;
}//Port_Reset(void)



void SysClk_Reset (void)
{
   uint i;                              // delay counter


//   OSCICN = 0x87;      //片内晶振


   WDTCN = 0xde;                       // disable watchdog timer
   WDTCN = 0xad;

   OSCXCN = 0x67;                      // start external oscillator with
                                       // 11.0592MHz crystal

   for (i=0; i <=255; i++) ;           // XTLVLD blanking interval (>1ms)

   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle

   OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                       // source and enable missing clock
                                       // detector
}//void SysClk_Reset (void)

void Interrupts_Init()
{
    //EIE1      = 0x08;    //AD0中断
    //IT01CF    = 0x00;    //P00为外部中断0 低电平有效
    IE        = 0x00;    //PS0 T0 enable
 EIE2      = 0x08;    //ADC1 enable
 EIP2      = 0x08;    //ADC1 high class
 IT0       = 1;    //INT0 下降沿中断
 IT1       = 1;
}

// Initialization function for device,
// Call Init_Device() from your main program
void init_var()
{
  
   Flag8=0;
   bfirst=0;
   //cnt_send=0;
   measurements=0;
   sample_mode=0;
   send_interval=1;
}

void Uart_Reset(void)
{
 //串口0
 SCON0=0x50;  //[sm00 sm10] sm20 [ren0] tb80 rb80 ti0 ri0

 //T2 for 波特率

  //baud=SYSCLK/(32*(65536-(RCAP2H:RCAP2L)))
  //4800: 0xffd8
  // [ 9600: 0xffdc ]
  //19200:0xffee
 TH2=0xff;
 TL2=0xb8;
 RCAP2H=0xff;
 RCAP2L=0xb8;
 //TH2=0xff;
 //TL2=0xdc;
 //RCAP2H=0xff;
 //RCAP2L=0xdc;
 T2CON=0x34;  //TF2 EXF2 [RCLK0] [TCLK0] EXEN2 [TR2] C/T2 CP/RL2
 ClearCommSendBuffer();
 
 
}//void Uart_Reset(void);

void Init_Device(void)
{
    SysClk_Reset();
 PORT_Reset();
    Timer0_Init();
 ADC_Init();   
 Uart_Reset();
    Interrupts_Init();
 //init_var();
}

 


 

ch372.c

 

 

 

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


#include


#define ERR_SUCCESS    0x00                       // 操作成功
#define ERR_PARAMETER   0x10                       // 参数错误
#define ERR_UNSUPPORT   0x80                       // 命令不支持
#define ERR_UNDEFINED   0xFF                       // 未定义的错误


//#define THIS_FIRMWARE_VER  0x10                       // 固件版本号
//#define THIS_APP_SYS_VER  0x10                       // 应用系统版本号
//#define THIS_APP_SYS_STR  "RA50"                     // 应用系统描述字符串


#define OP_CMD                  1                          // 命令操作码
#define OP_DATA                 0                          // 数据操作码
#define DELAY_TIMES             2                         // 延时2微秒
#define DELAY_CNT_NUMS          16*DELAY_TIMES                // 延时2微秒所需的时钟周期数(对于22.1184MHz晶振,每个微秒包含22.1184个时钟周期)
//#define MY_USB_VENDOR_ID  0x4348                     // USB设备制造商标识
//#define MY_USB_PRODUCT_ID  0x5537                     // USB设备产品标识


sbit  USB_CS      =  P2^4;
sbit  USB_INT     =  P3^0;                                
sbit  USB_A0      =  P2^3;                                
sbit  USB_WR      =  P2^1;                                
sbit  USB_RD      =  P2^2;                                
sfr   USB_DATA    =  0x96;                                
//#define get_usb P7
//#define set_usb(dat1) P7=dat1

 


void Delay2us( )
{
  INT8U i;

  i = (INT8U)DELAY_CNT_NUMS;
  while (--i);
}



void CH375_WR_CMD_PORT(INT8U dat)
{
  //USB_CS = 0;
  //INT8U a;
 
  //set_usb(dat);
  USB_WR = 1;
  USB_RD = 1;
  Delay2us(); 
  USB_A0 = OP_CMD;
  USB_DATA = dat;                                        // 准备写命令
 
  USB_CS = 0;
  USB_WR = 0;
 
  //USB_CS = 0;
  //USB_WR = 0;                                                // 开始写命令 延时80ns
  //Delay2us();
  Delay2us();
  USB_WR = 1;
  USB_CS = 1;                                             // 结束写命令(USB_WR信号的有效时间不能超过10us)
  //USB_A0 = 1;
  //P7=0xff;
  //P1|=0x80;
 
}


void CH375_WR_DAT_PORT(INT8U dat)
{
  //USB_CS = 0;
  //set_usb(dat);
  USB_WR = 1;
  USB_RD = 1;
  Delay2us(); 
  USB_A0 = OP_DATA;                                        // 准备写数据
  USB_DATA = dat;                                          // 准备数据
 
  USB_CS = 0;
  USB_WR = 0;                                              // 开始写数据
  //USB_CS = 0;              //延时80ns
  //USB_WR = 0; 
  Delay2us();
  USB_WR = 1;                                              // 结束写命令(USB_WR信号的有效时间不能超过10us)
  USB_CS = 1;
  //USB_A0 = 1;
  //P7=0xff;
  //P1|=0x80;
}

INT8U CH375_RD_DAT_PORT(void)
{
  INT8U nData;
  //USB_CS   = 0;
  USB_WR   = 1;
  USB_RD   = 1;
  Delay2us();
  USB_DATA = 0xFF;                                         // 将USB_DATA(P4口)配置为数字输入
  USB_A0 = OP_DATA;                                        // 准备读数据
  USB_CS   = 0;
  USB_RD = 0;                                              // 开始读数据
  //Delay2us();
  Delay2us();
  //USB_CS   = 0;               //延时80ns
  //USB_RD = 0;
  nData = USB_DATA;                                        // 读取数据
  USB_RD = 1;                                              // 结束读命令(USB_RD信号的有效时间不能超过10us)
  USB_CS = 1;
  //USB_A0 = 1;
  return nData;                                            // 返回读取的数据
}


void CH375_Init(void)
{
  INT8U i,j;
  INT16U k;
 
  //CH375_WR_CMD_PORT(CMD_SET_USB_ID);                       // 设置外部自定义的USB设备VID和PID,可选操作
  //CH375_WR_DAT_PORT((INT8U)MY_USB_VENDOR_ID);              // 写入厂商ID的低字节
  //CH375_WR_DAT_PORT((INT8U)(MY_USB_VENDOR_ID>>8));         // 写入厂商ID的高字节
  //CH375_WR_DAT_PORT((INT8U)MY_USB_PRODUCT_ID);             // 写入产品ID的低字节
  //CH375_WR_DAT_PORT((INT8U)(MY_USB_PRODUCT_ID>>8));        // 写入产品ID的高字节
  CH375_WR_CMD_PORT(CMD_RESET_ALL);
  for (k=0;k<25000;k++)
       Delay2us();
 
  CH375_WR_CMD_PORT(CMD_SET_USB_MODE);
  CH375_WR_DAT_PORT(2);

 
  for (i=100; i!=0; i--)
  {
    j=CH375_RD_DAT_PORT();
    if (j == CMD_RET_SUCCESS)
 {
    j=j;
      break;
 }   
  }

 
  //IT0 = 0;                                                 // 置外部信号为低电平触发
  //IE0 = 0;                                                 // 清中断标志
  //EX0 = 1;                                                 // 允许CH372中断,假定CH372的INT#引脚连接到单片机的INT0
}

void CH375_process()
{
  INT8U           id;
  INT8U           cnt;
  INT8U           IntStatus;
  //PUINT8C         str;
  //USB_DOWN_BUFFER down;
  //USB_UP_BUFFER   up;
  if (USB_INT)
      return;
//#define IntStatus   dat                                    // 节约一个变量存储单元
  CH375_WR_CMD_PORT((INT8U)CMD_GET_STATUS);                // 获取中断状态并取消中断请求
  IntStatus = CH375_RD_DAT_PORT();                         // 获取中断状态
  //USB_INT = 1;
  //IE0 = 0;                                                 // 清中断标志,与单片机硬件有关,对应于INT0中断
  // 批量端点下传成功,接收到命令包
  if (IntStatus == USB_INT_EP2_OUT)
  { 
     CH375_WR_CMD_PORT((INT8U)CMD_RD_USB_DATA);             // 从当前USB中断的端点缓冲区读取数据块,并释放缓冲区
     cnt = CH375_RD_DAT_PORT();                             // 首先读取后续数据长度
     if ((cnt == 0) || (cnt >38))                                          // 长度为0,没有数据,在某些应用中也可以将长度0定义为一种特殊命令
     {
       CH375_WR_CMD_PORT((INT8U)CMD_SET_ENDP7);             // 设置USB端点2的IN,也就是批量上传端点
       CH375_WR_DAT_PORT((INT8U)0x0E);                      // 同步触发位不变,设置USB端点2的IN正忙,返回NAK,实际是清除上传缓冲区的已有内容
       return;
     }
     id = 0;
     do
     {
       down[id] = CH375_RD_DAT_PORT();                      // 接收命令包的数据
       id++;
     } while (--cnt);
                                     
    
  // 命令包反码校验错误,放弃该下传包
     if (down[--id]==calc_sum(&down[0]))
      brev=1;
  }
  else if (IntStatus == USB_INT_EP2_IN)                    // 批量数据发送成功,状态包已发送
    CH375_WR_CMD_PORT((INT8U)CMD_UNLOCK_USB);              // 释放当前USB缓冲区,收到上传成功中断后,必须解锁USB缓冲区,以便继续收发
  else if (IntStatus == USB_INT_EP1_IN)                    // 中断数据发送成功,本程序未用到
    CH375_WR_CMD_PORT((INT8U)CMD_UNLOCK_USB);              // 释放当前USB缓冲区
  else
    CH375_WR_CMD_PORT((INT8U)CMD_UNLOCK_USB);
  // 内置固件的USB方式下不应该出现其它中断状态
}

 

 

 

global.c

 

 

#include "def.h"


INT8U xdata up[64];
//INT8U xdata up1[64];
INT8U xdata down[64];
INT8U xdata data_array[DATA_SIZE];
INT8U xdata com_buffer[10];
INT8U xdata ad_data[1400];
//INT16U xdata ph_ad_value[18];

INT8U bdata Flag8;
//INT8U bdata Flag8;
sbit brev=Flag8^0;
sbit bstart=Flag8^1;
sbit bsample=Flag8^2;
sbit bover=Flag8^3;
sbit bfirst=Flag8^5;
sbit bsent=Flag8^6;

INT8U idata cnt_send;
INT16U idata ph_result;
INT16U idata ph_filter_result;
INT8U idata send_interval;
INT8U idata send_no;

INT8U idata measurements ;  // measurement counter
INT16U idata sample_cnt;
INT8U  idata sample_mode;

//INT8U idata x_data[2];
//INT8U idata y_data[2];
//INT8U idata z_data[2];

 

 

 

T0.C

 

#include "include.h"
//-------------------------------------------------------------------------------
//子程序名称:T0
//功能:T0中断处理函数
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void T0(void) interrupt 1 using 1
{
 TH0       = TH0_VALUE;
 TL0       = TL0_VALUE;
 if (bstart)
  cnt_send++;
}

void Int1() interrupt 2 using 2 //int0 0003h
{
 if (bstart)
    {
      bfirst=1;  
   EN_INT0;
   DIS_INT1;
    }
}

void Int0() interrupt 0 using 0 //int0 0003h
{
  //bmenu_ok1=1;
  // INT8U temp12;
  
   if (bfirst)
      {
      
     if (!bsample)
        {
        measurements++;
     if (measurements==32)
        {
          bsample=1;
       sample_cnt=0;
     }
     }
     else
        {
       if (sample_cnt ^ 1350)
       {       
     // _nop_();
     // _nop_();
     // _nop_();
      //_nop_();
      //_nop_();
      ADC1CN&=0xdf;  //启动AD转换
      //if (ADC1CN & 0x10)
      //   {
     //   temp12=ad_data[sample_cnt];
     //   ad_data[sample_cnt++]=temp12;
     // }
     // else
      ADC1CN|=0x10;
       }
    else
       {
      bover=1;     
         DIS_INT0;
       }
     }
    
   }

  
 
}
//-------------------------------------------------------------------------------
//子程序名称:adv0
//功能:AD中断处理函数
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void adv0() interrupt 17 using 3 //int0 0003h
{
  ADC1CN&=0xdf;
  ad_data[sample_cnt++]=ADC1;
 
}

 

 

fun.C

 

#include "include.h"

//-------------------------------------------------------------------------------
//子程序名称:pc_process()
//功能:上机位处理
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void pc_process()
{
    INT8U idata tmp3;
  tmp3=down[0];
     switch(tmp3)
  {
     case LINK_OPEN:
    up[0]=PC_ORDER_SURE;
             up[1]=2;
             up[2]=calc_sum(&up[0]);
       break;
  case STOP_ORDER:
       stop();
       up[0]=PC_ORDER_SURE;
             up[1]=2;
             up[2]=calc_sum(&up[0]);
    break;
  case LINK_CLOSE:
       up[0]=PC_ORDER_SURE;
             up[1]=2;
             up[2]=calc_sum(&up[0]);
   
    break;
  
  case START_SEND_PC:
       sample_mode=0;
       start();
    //EN_INT;
    return;
    break;   
  //case AD_FILTER_READ:
       //start();
    //sample_mode=1;
  //  return;   
  //  break;
   
  case PC_STANDAR:
    //if (down[3] ^ CHANNEL_NO)
    //   return;
   
    stop();
    //send_xiaweiji();
    return;  
       break;
  //case PC_ADJUST:
       //if (down[2] ^ CHANNEL_NO)
    //   return;
    //data_array[1]=down[3];
    //data_array[2]=down[4];
    //WriteFlash();
       //up[0]=PC_ORDER_SURE;
          //up[1]=2;
          //up[2]=calc_sum(&up[0]);

    //stop();
    //send_xiaweiji();
  //  return;
  //  break;
  default:
       return;
    break;
  
  }
  usb_send_pc(&up[0]);
}
//-------------------------------------------------------------------------------
//子程序名称:usb_send_pc(INT8U * buf)
//功能:USB发送函数
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void usb_send_pc(INT8U * buf)
{
 INT8U idata cnt;
    //INT8U  * buf;
    
 CH375_WR_CMD_PORT(CMD_WR_USB_DATA7); 

 cnt=64;//强制指令回数64个, 为了满足沁恒的驱动
 CH375_WR_DAT_PORT(cnt); 
 
  
  
   do
   {
     //WATCH_DOG;
     //Delay2us();
  //Delay2us();
     CH375_WR_DAT_PORT(*buf);  
     buf ++;
  //CH375_WR_DAT_PORT(11);
    } while ( -- cnt );
 

}
//-------------------------------------------------------------------------------
//子程序名称:send_real_pc()
//功能:连续数据发送
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void send_real_pc(INT8U idata num_no)
{
   INT8U idata i;
   INT16U idata j;
   INT8U * p_ad;
      up[0]=0xe0;
   up[1]=53;
   up[2]=num_no;
  
   j=num_no*50;
   p_ad=&ad_data[0]+j;
   for (i=0;i<50;i++)
       up[3+i]=*p_ad++;
    //up[3+i]=i*2;
 
   //up[11]=0;
   //up[20]=0;
   //up[29]=0;
   //up[38]=(INT8U)send_no;
   //up[39]=(INT8U)(send_no>>8);
   //up[40]=0;
   //up[41]=0;
   up[53]=calc_sum(&up[0]);
      usb_send_pc(&up[0]);

}


//-------------------------------------------------------------------------------
//子程序名称:calc_sum(INT8U * buf)
//功能:计算累加和
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
INT8U calc_sum(INT8U * buf)
{
 
 INT8U idata sum;
 INT8U idata point;
 //INT8U dat;
 sum=0;point=0;
 do
 {
  sum=sum+buf[point];
  point++;
  }while(point //dat=sum;
 return sum; 
 }
 
 //-------------------------------------------------------------------------------
//子程序名称:start()
//功能:启动采样
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
 void start()
{
     //bsent=1; 
     bstart=1;
  EN_INT1;
  bover=0;    
  bfirst=0;
  bsample=0;
  measurements=0; 
  //bover=0;
  //if (mode)
  //   bsingle=1;
  //else
  //   bsingle=0;
  //measurements = 0;
  //accumulator=0;
  //send_no=0;
  //cnt_send=0;
 
}
//-------------------------------------------------------------------------------
//子程序名称:stop()
//功能:停止采样
//修改日期:2011.08.08
//修改人:njgwx
//-------------------------------------------------------------------------------
void stop()
{
   bstart=0;
   bover=0;
   DIS_INT1;
   DIS_INT0;
  //bsent=0; 
}

 

 

uart.c

 

#include
//#define DB_SENDMAXSIZE 48
#define DB_SENDMAXSIZE 16

//bit CommRecDataOverflowFlag,FlagRecComm,SendItComm;

INT8U idata CommSendBufferHead=0;
INT8U idata CommSendBufferTail=0;
INT8U idata CommSendBuffer[DB_SENDMAXSIZE];

bit SendItComm;



void ClearCommSendBuffer(void)
{
   
    CommSendBufferHead=CommSendBufferTail=0;
    SendItComm=1;
 //step=0;valid_sum=0;
    //for (tmp=0;tmp<13;tmp++)
    //    com_up_buf[tmp]=0;
}





void sendcommbuffer(INT8U * base, INT8U idata size)
{
    INT8U idata ii4;
    ii4=0;
 if (!size) { return; } 
 while (ii4 { 
  CommSendBuffer[CommSendBufferTail]=base[ii4];
  ii4++;
  CommSendBufferTail++;
  if (CommSendBufferTail==DB_SENDMAXSIZE)
  {
   CommSendBufferTail=0;
  }
 }
 if (SendItComm)
 { 
  SBUF1=CommSendBuffer[CommSendBufferHead];
        SendItComm=0;
 }
}

void CommISR(void) interrupt 4
{
 if (_testbit_(TI0))
 {
  TI0=0;
  CommSendBufferHead++;  
  if (CommSendBufferHead==DB_SENDMAXSIZE)
  { 
   CommSendBufferHead=0;
  }
  if (CommSendBufferHead!=CommSendBufferTail)
  { 
   SBUF0=CommSendBuffer[CommSendBufferHead]; // send the next byte
   SendItComm=0;
  }
  else
  {
   SendItComm=1;
  }
  
 } 
}

 

main.c

 

 #include "include.h"

 void main()
 {
     //INT8U temp1;
  //INT16U k;

  Init_Device();
  init_var();
  CH375_Init();
  //load_default_parm();
  //WriteFlash();
  //Read_eeprom_data();
  //PCA_Init();
  TR0=1;
  EA=1;
  //bstart=1;//dubug ?????
     //EN_INT;
  while (1)
  {
     //WATCH_DOG;
 
     CH375_process();// ch374处理
     if (brev)     //上位机命令处理
     {
       brev=0;
       pc_process();
     }
 
  // sample over send data to PC
  if (bover)  //CCD一帧数据采集完成
     {
       TF0=0;      
       ET0=1;
       cnt_send=0;
    send_no=0;     
   
    do
    {
        CH375_process();
        if (cnt_send>1)  //发送实时AD值
        {
      
       //up[0]=ad_data[send_no];
       //#ifdef debug
       //    sendcommbuffer(&up[0],1);
          //#else
       //TH0=0;
       //TL0=0;
       if (send_no ^ 27)           
             send_real_pc(send_no);
       //#endif
      
       send_no++;
      
       cnt_send=0;       
     }
    }while (send_no<28);   //USB发送28数据包
   
     cnt_send=0;     //延时
     do
     {
       if (cnt_send>200)
        break;
     }
     while (1);

     ET0=0;    
     bover=0;    
     bfirst=0;
     bsample=0;
        measurements=0;   
     EN_INT1;
     }
  }

 }



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址