找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2304|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

基于51單片機(jī)的雙核系統(tǒng)設(shè)計(jì)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
本系統(tǒng)是一個(gè)基于51單片機(jī)的雙核系統(tǒng)設(shè)計(jì)。采用單片機(jī)型號STC12C60S2,使用串口作為數(shù)據(jù)總線,占用兩個(gè)io作為控制總線。例程是驅(qū)動(dòng)LCD1602,用一個(gè)單片機(jī)P0口的低四位驅(qū)動(dòng)1602dat口的高四位,另一個(gè)單片機(jī)P0口低四位驅(qū)動(dòng)1602dat口的高四位。顯示內(nèi)容為兩個(gè)12單片機(jī)的P1.0采集電位器的電壓量。同時(shí)第二個(gè)單片機(jī)輸出硬件pwm。其實(shí)也不能說是雙核吧,但是時(shí)序配合必須很好,不然1602驅(qū)動(dòng)不起來從核只需要對硬件初始化和io口操作,邏輯在主核實(shí)現(xiàn),然后傳給從核,從核處理后對相應(yīng)io口操作。

不能發(fā)視頻就很尷尬。
貼出代碼,感興趣的朋友可以試下。需要說明的是,PWM可以通過數(shù)據(jù)總線傳給第二個(gè)單片機(jī)的,改天試試。有想法的朋友可以交流下。
畫重點(diǎn)!敲黑板!
我做這個(gè)完全處于興趣,覺得沒什么用的可以劃走了。
接下來的計(jì)劃是做一個(gè)四核系統(tǒng)。

制作出來的實(shí)物圖如下:


/*************** 用戶定義參數(shù) *****************************/

#define MAIN_Fosc                22118400L        //define main clock

#define Baudrate1                9600                //define the baudrate, 如果使用BRT做波特率發(fā)生器,則波特率跟串口2一樣
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define Baudrate2                9600                //define the baudrate2,
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define                BUF_LENTH        128                //定義串口接收緩沖長度

/**********************************************************/

#include<reg51.h>        
#include<intrins.h>  //包含_nop_()函數(shù)定義的頭文件
#include<fun.h>

sfr AUXR1 = 0xA2;
sfr        AUXR = 0x8E;

sfr S2CON = 0x9A;        //12C5A60S2雙串口系列
sfr S2BUF = 0x9B;        //12C5A60S2雙串口系列
sfr IE2   = 0xAF;        //STC12C5A60S2系列
sfr BRT   = 0x9C;

unsigned char         uart1_wr=0;                //寫指針
unsigned char         uart1_rd=0;                //讀指針
unsigned char         xdata RX1_Buffer[BUF_LENTH];
bit                B_TI;

unsigned char         uart2_wr=0;                //寫指針
unsigned char         uart2_rd=0;                //讀指針
unsigned char         xdata RX2_Buffer[BUF_LENTH];
bit                B_TI2;


/****************** 編譯器自動(dòng)生成,用戶請勿修改 ************************************/

#define T1_TimerReload        (256 - MAIN_Fosc / 192 / Baudrate1)                        //Calculate the timer1 reload value        at 12T mode
#define BRT_Reload                (256 - MAIN_Fosc / 12 / 16 / Baudrate2)                //Calculate BRT reload value

#define        TimeOut1                (28800 / (unsigned long)Baudrate1 + 2)
#define        TimeOut2                (28800 / (unsigned long)Baudrate2 + 2)

#define        TI2                                (S2CON & 0x02) != 0
#define        RI2                                (S2CON & 0x01) != 0
#define        CLR_TI2()                S2CON &= ~0x02
#define        CLR_RI2()                S2CON &= ~0x01

/******LCD1602***********/
sbit p00=P0^0;
sbit p01=P0^1;
sbit p02=P0^2;
sbit p03=P0^3;
sbit p04=P0^4;
sbit p05=P0^5;
sbit p06=P0^6;

sbit RS=P2^6;    //寄存器選擇位,將RS位定義為P2.6引腳
sbit RW=P2^5;    //讀寫選擇位,將RW位定義為P2.5引腳
sbit E=P2^7;     //使能信號位,將E位定義為P2.7引腳
sbit BF=P0^7;    //忙碌標(biāo)志位,,將BF位定義為P0.7引腳

sbit tx=P2^0;    //從機(jī)狀態(tài)線
sbit rx=P2^1;    //從機(jī)狀態(tài)線

unsigned char flag1,flag2,flag3,flag4;//發(fā)送指令位的值
unsigned char  string[ ]={"Core1:      V   "},string2[ ]={"Core2:      V   "};

/*****************ADC配置*************************/

sfr P1ASF     = 0x9D;        //12C5A60AD/S2系列模擬輸入(AD或LVD)選擇
sfr ADC_CONTR = 0xBC;        //帶AD系列
sfr ADC_RES   = 0xBD;        //帶AD系列
sfr ADC_RESL  = 0xBE;        //帶AD系列

//                                                                7       6      5       4         3      2    1    0   Reset Value
//sfr ADC_CONTR = 0xBC;                ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000        //AD 轉(zhuǎn)換控制寄存器
#define ADC_OFF()        ADC_CONTR = 0
#define ADC_ON                (1 << 7)
#define ADC_90T                (3 << 5)
#define ADC_180T        (2 << 5)
#define ADC_360T        (1 << 5)
#define ADC_540T        0
#define ADC_FLAG        (1 << 4)        //軟件清0
#define ADC_START        (1 << 3)        //自動(dòng)清0
#define ADC_CH0                0
#define ADC_CH1                1
#define ADC_CH2                2
#define ADC_CH3                3
#define ADC_CH4                4
#define ADC_CH5                5
#define ADC_CH6                6
#define ADC_CH7                7
unsigned int        adc10_start(unsigned char channel);        //channel = 0~7
double adc;                                                                                          
/********************PWM******************************/
#define                PCA_IDLE_DISABLE        0                //1: MCU在IDLE模式時(shí)禁止PCA工作。        0:  MCU在IDLE模式時(shí)允許PCA工作。
#define                PCA_SOURCE_SELECT        4                //選擇PCA的基準(zhǔn)時(shí)鐘源。
                                                                                //0:系統(tǒng)時(shí)鐘Fosc/12。
                                                                                //1:系統(tǒng)時(shí)鐘Fosc/2。
                                                                                //2:定時(shí)器0的溢出。
                                                                                //3:ECI/P3.4腳的外部時(shí)鐘輸入(最大=Fosc/2)。
                                                                                //4:系統(tǒng)時(shí)鐘Fosc。
                                                                                //5:系統(tǒng)時(shí)鐘Fosc/4。
                                                                                //6:系統(tǒng)時(shí)鐘Fosc/6。
                                                                                //7:系統(tǒng)時(shí)鐘Fosc/8。
sfr CCON = 0xD8;
sfr CMOD = 0xD9;
sfr CCAPM0 = 0xDA;        //PCA module 0 work mode
sfr CCAPM1 = 0xDB;        //PCA module 1 work mode
sfr CL     = 0xE9;        //PCA counter
sfr CCAP0L = 0xEA;        //PCA模塊0的捕捉/比較寄存器低8位。
sfr CCAP1L = 0xEB;        //PCA模塊1的捕捉/比較寄存器低8位。
sfr PCA_PWM0 = 0xF2;        //PCA模塊0 PWM寄存器。
sfr PCA_PWM1 = 0xF3;        //PCA模塊1 PWM寄存器。
sfr CH     = 0xF9;
sfr CCAP0H = 0xFA;                //PCA模塊0的捕捉/比較寄存器高8位。
sfr CCAP1H = 0xFB;                //PCA模塊1的捕捉/比較寄存器高8位。

sbit CCF0  = CCON^0;        //PCA 模塊0中斷標(biāo)志,由硬件置位,必須由軟件清0。
sbit CCF1  = CCON^1;        //PCA 模塊1中斷標(biāo)志,由硬件置位,必須由軟件清0。
sbit CR    = CCON^6;        //1: 允許PCA計(jì)數(shù)器計(jì)數(shù),必須由軟件清0。
sbit CF    = CCON^7;        //PCA計(jì)數(shù)器溢出(CH,CL由FFFFH變?yōu)?000H)標(biāo)志。PCA計(jì)數(shù)器溢出后由硬件置位,必須由軟件清0。

#define                PWM0_NORMAL()        PCA_PWM0 = 0        //PWM0正常輸出(默認(rèn))
#define                PWM0_OUT_0()        PCA_PWM0 = 3        //PWM0一直輸出0
#define                PWM1_NORMAL()        PCA_PWM1 = 0        //PWM1正常輸出(默認(rèn))
#define                PWM1_OUT_0()        PCA_PWM1 = 3        //PWM1一直輸出0


/*****************************************************
函數(shù)功能:延時(shí)1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認(rèn)為是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<10;i++)
          for(j=0;j<33;j++)
           ;                 
}
/*****************************************************
函數(shù)功能:延時(shí)若干毫秒
入口參數(shù):n
***************************************************/
void delay(unsigned char n)
{
   unsigned char i;
        for(i=0;i<n;i++)
           delay1ms();
}
/*****************************************************
函數(shù)功能:判斷液晶模塊的忙碌狀態(tài)
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsigned char BusyTest(void)
  {
    bit result;
        RS=0;       //根據(jù)規(guī)定,RS為低電平,RW為高電平時(shí),可以讀狀態(tài)
    RW=1;
    E=1;        //E=1,才允許讀寫
    _nop_();   //空操作
    _nop_();
    _nop_();
    _nop_();   //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
    result=BF;  //將忙碌標(biāo)志電平賦給result
        E=0;
    return result;
  }
/*****************************************************
函數(shù)功能:將模式設(shè)置指令或顯示地址寫入液晶模塊
入口參數(shù):dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{   
    flag1=0;flag2=0;flag3=0;flag4=0;
//   while(BusyTest()==1); //如果忙就等待
         RS=0;                  //根據(jù)規(guī)定,RS和R/W同時(shí)為低電平時(shí),可以寫入指令
         RW=0;   
         E=0;                   //E置低電平(根據(jù)表8-6,寫指令時(shí),E為高脈沖,
                             // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"

         _nop_();
         _nop_();             //空操作兩個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
        
         
          if((dictate & 0x10 )){
          flag1=1;  }else
          {flag1=0;}
          if((dictate & 0x20 )){
          flag2=1;  }else
          {flag2=0;}
          if((dictate & 0x40 )){
          flag3=1;  }else
          {flag3=0;}
          if((dictate & 0x80 )){
          flag4=1;  }else
          {flag4=0;}

             tx=0;                                                          //可以執(zhí)行下步
          delay(30);
        if(flag1==1&&flag2==1&&flag3==1&&flag4==1)        {PrintString1("L111100000");}        
   else if(flag1==0&&flag2==1&&flag3==1&&flag4==1)        {PrintString1("L011100000");}  
   else if(flag1==1&&flag2==0&&flag3==1&&flag4==1)        {PrintString1("L101100000");}
   else if(flag1==0&&flag2==0&&flag3==1&&flag4==1)        {PrintString1("L001100000");}
   else if(flag1==1&&flag2==1&&flag3==0&&flag4==1)        {PrintString1("L110100000");}   
   else if(flag1==0&&flag2==1&&flag3==0&&flag4==1)        {PrintString1("L010100000");}  
   else if(flag1==1&&flag2==0&&flag3==0&&flag4==1)        {PrintString1("L100100000");}
   else if(flag1==0&&flag2==0&&flag3==0&&flag4==1)        {PrintString1("L000100000");}
   else if(flag1==1&&flag2==1&&flag3==1&&flag4==0)        {PrintString1("L111000000");}
   else if(flag1==0&&flag2==1&&flag3==1&&flag4==0)        {PrintString1("L011000000");}
   else if(flag1==1&&flag2==0&&flag3==1&&flag4==0)        {PrintString1("L101000000");}  
   else if(flag1==0&&flag2==0&&flag3==1&&flag4==0)        {PrintString1("L001000000");}
   else if(flag1==1&&flag2==1&&flag3==0&&flag4==0)        {PrintString1("L110000000");}
   else if(flag1==0&&flag2==1&&flag3==0&&flag4==0)        {PrintString1("L010000000");}
   else if(flag1==1&&flag2==0&&flag3==0&&flag4==0)        {PrintString1("L100000000");}         
   else if(flag1==0&&flag2==0&&flag3==0&&flag4==0)  {PrintString1("L000000000");}  
   delay(30);                                                  //等待從機(jī)將信號置零
   tx=1;


     while(rx==1);                                          //如果從機(jī)已執(zhí)行完
          if((dictate & 0x01 )){
          p00=1;  }else
          {p00=0;}
          if((dictate & 0x02 )){
          p01=1;  }else
          {p01=0;}
          if((dictate & 0x04 )){
          p02=1;  }else
          {p02=0;}
          if((dictate & 0x08 )){
          p03=1;  }else
          {p03=0;}
        
         _nop_();
         _nop_();
         _nop_();
         _nop_();               //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
        
         E=1;                   //E置高電平

         _nop_();
         _nop_();
         _nop_();
         _nop_();               //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
        
         E=0;                   //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開始執(zhí)行命令
         
}
/*****************************************************
函數(shù)功能:指定字符顯示的實(shí)際地址
入口參數(shù):x
***************************************************/
void WriteAddress(unsigned char x)
{
     WriteInstruction(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
}
/*****************************************************
函數(shù)功能:將數(shù)據(jù)(字符的標(biāo)準(zhǔn)ASCII碼)寫入液晶模塊
入口參數(shù):y(為字符常量)
***************************************************/
void WriteData(unsigned char y)
{
     flag1=0;flag2=0;flag3=0;flag4=0;
   //  while(BusyTest()==1);  
          RS=1;           //RS為高電平,RW為低電平時(shí),可以寫入數(shù)據(jù)
          RW=0;
          E=0;            //E置低電平(根據(jù)表8-6,寫指令時(shí),E為高脈沖,
                       // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
          if(y & 0x10 ){
          flag1=1;  }else
          {flag1=0;}
          if(y & 0x20 ){
          flag2=1;  }else
          {flag2=0;}
          if(y & 0x40 ){
          flag3=1;  }else
          {flag3=0;}
          if(y & 0x80 ){
          flag4=1;  }else
          {flag4=0;}  

            tx=0;                                                          //可以執(zhí)行下步
         delay(30);
        if(flag1==1&&flag2==1&&flag3==1&&flag4==1)        {PrintString1("L111100000");}        
   else if(flag1==1&&flag2==1&&flag3==1&&flag4==0)        {PrintString1("L111000000");}  
   else if(flag1==1&&flag2==1&&flag3==0&&flag4==1)        {PrintString1("L110100000");}
   else if(flag1==1&&flag2==1&&flag3==0&&flag4==0)        {PrintString1("L110000000");}
   else if(flag1==1&&flag2==0&&flag3==1&&flag4==1)        {PrintString1("L101100000");}
   else if(flag1==1&&flag2==0&&flag3==1&&flag4==0)        {PrintString1("L101000000");}  
   else if(flag1==1&&flag2==0&&flag3==0&&flag4==1)        {PrintString1("L100100000");}
   else if(flag1==1&&flag2==0&&flag3==0&&flag4==0)        {PrintString1("L100000000");}
   else if(flag1==0&&flag2==1&&flag3==1&&flag4==1)        {PrintString1("L011100000");}  
   else if(flag1==0&&flag2==1&&flag3==1&&flag4==0)        {PrintString1("L011000000");}
   else if(flag1==0&&flag2==1&&flag3==0&&flag4==1)        {PrintString1("L010100000");}
   else if(flag1==0&&flag2==1&&flag3==0&&flag4==0)        {PrintString1("L010000000");}
   else if(flag1==0&&flag2==0&&flag3==1&&flag4==1)        {PrintString1("L001100000");}
   else if(flag1==0&&flag2==0&&flag3==1&&flag4==0)        {PrintString1("L001000000");}
   else if(flag1==0&&flag2==0&&flag3==0&&flag4==1)        {PrintString1("L000100000");}
   else if(flag1==0&&flag2==0&&flag3==0&&flag4==0)        {PrintString1("L000000000");}
     delay(30);
         tx=1;
         
          while(rx==1);        
      if((y & 0x01 )){
          p00=1;  }else
          {p00=0;}
          if((y & 0x02 )){
          p01=1;  }else
          {p01=0;}
          if((y & 0x04 )){
          p02=1;  }else
          {p02=0;}
          if((y & 0x08 )){
          p03=1;  }else
          {p03=0;}

          _nop_();
          _nop_();
           _nop_();
      _nop_();       //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
               
          E=1;           //E置高電平
        
          _nop_();
          _nop_();
          _nop_();
          _nop_();        //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
        
          E=0;            //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開始執(zhí)行命令
}
/*****************************************************
函數(shù)功能:對LCD的顯示模式進(jìn)行初始化設(shè)置
***************************************************/
void InitLCD1602(void)
{
    delay(200);               //延時(shí)15ms,首次寫指令時(shí)應(yīng)給LCD一段較長的反應(yīng)時(shí)間
        WriteInstruction(0x38);         //0x38
        delay(200);
        WriteInstruction(0x0c);  
        delay(200);
        WriteInstruction(0x04);  
        delay(200);
        WriteInstruction(0x01);  //清屏幕指令,將以前的顯示內(nèi)容清除
        delay(200);
}

/**********************************************************/


void        main(void)
{
    unsigned char i,j,adc_i,adc_result[5],core2_adc[5],core_adc_i=1,core_adc_lcd1602=0;
        unsigned int adc_j;
        unsigned char y=0;
        unsigned char core2_i;
        /*******PWM***************/
        unsigned char pwm1,pwm0;
        unsigned int pwm_i;
        /*******ADC配置***********/
        double adc;
        P1ASF = 0XE3;//0xff;                        
        ADC_CONTR = ADC_360T | ADC_ON;//只選擇p10 若是所以選ADC_ON;
        /********************PWM配置*****************************/
        pwm0 = 0;                        // PWM0 初始值
        pwm1 = 0;                        // PWM1 初始值
        
        CCAP0H = pwm0;                //set PWM wide
        CCAPM0 = 0x42;                //0x42 Setup PCA module 0 in PWM mode
        
        CCAP1H = pwm1;                //set PWM wide
        CCAPM1 = 0x42;                //0x42 Setup PCA module 1 in PWM mode

        CMOD = (PCA_IDLE_DISABLE << 7) | (PCA_SOURCE_SELECT << 1);        //初始化PCA模式寄存器。
        CL = 0x00;                //clear PCA counter
        CH = 0x00;
        CR = 1;                        //Start PCA counter
        /********************************************************/
    uart1_init();
        uart2_init();
    InitLCD1602();//調(diào)用LCD初始化函數(shù)


//        AUXR |=  0x01;                //串口1使用獨(dú)立波特率發(fā)生器, 波特率跟串口2一樣
//        AUXR1 |= (1<<4);        //將UART2從P1口切換到 RXD2--P1.2切換到P4.2   TXD2---P1.3切換到P4.3

        WriteInstruction(0x01);//清顯示:清屏幕指令
        WriteAddress(0x00);    //設(shè)置顯示位置為第一行的第0個(gè)字
        for(i=0;i<16;i++){
        WriteData(string[ i]);
     }
        WriteAddress(0xc0);    //設(shè)置顯示位置為第二行的第0個(gè)字
        for(j=0;j<16;j++){
        WriteData(string2[j]);
   }
        while(1){
           
                /*
                if(uart2_rd != uart2_wr)        //串口2轉(zhuǎn)發(fā)
                {
                        UART2_TxByte(RX2_Buffer[uart2_rd]);
                        if(++uart2_rd >= BUF_LENTH)                uart2_rd = 0;
                }
                */
         
        //PWM
    //for(pwm_i=0; pwm_i<3000; pwm_i++);        //延時(shí)一下

        pwm0+=20;
        pwm1++;
        CCAP0H = pwm0;                //set PWM wide
        CCAP1H = pwm1;                //set PWM wide
        
        //ADC
    //for(adc_i=0; adc_i<8; adc_i++){ //8路ADC  
        adc_j = adc10_start(0/*adc_i*/);
        adc=(double)adc_j/2.048;
        adc_result[0]=(int)adc/1000 + '0';
        adc_result[1]=(int)adc%1000/100 + '0';
        adc_result[2]='.';
        adc_result[3]=(int)adc%100/10 + '0';
        adc_result[4]=(int)adc%10 + '0';
    //}
        //LCD1602
        WriteAddress(0x07);    //設(shè)置顯示位置為第一行的第0個(gè)字
        for(i=0;i<5;i++){
        WriteData((char)adc_result[ i]);
}
        WriteAddress(0xc7);    //設(shè)置顯示位置為第二行的第0個(gè)字
    if(uart1_rd !=6/* uart1_wr*/&&RX1_Buffer[0]=='A'){        //串口0轉(zhuǎn)發(fā)
                for(core_adc_i=1,core_adc_lcd1602=0;core_adc_i<6,core_adc_lcd1602<5;core_adc_i++,core_adc_lcd1602++){
                core2_adc[core_adc_lcd1602]=RX1_Buffer[core_adc_i];
          }
     }
        for(core2_i=0;core2_i<5;core2_i++){
        WriteData((char)core2_adc[core2_i]);//此處數(shù)據(jù)接收無問題
        //UART2_TxByte((char)core2_adc[core2_i]);
        if(++uart1_rd >= BUF_LENTH)                uart1_rd = 0;
          }        
        WriteInstruction(0x38);         //0x38
  }
}

void        UART1_TxByte(unsigned char dat)
{
        B_TI = 0;
        SBUF = dat;
        while(!B_TI);
        B_TI = 0;
}

void        UART2_TxByte(unsigned char dat)
{
        B_TI2 = 0;
        S2BUF = dat;
        while(!B_TI2);
        B_TI2 = 0;
}

void PrintString1(unsigned char *puts)                //發(fā)送一串字符串
{
    for (; *puts != 0;        puts++)  UART1_TxByte(*puts);         //遇到停止符0結(jié)束
}

void PrintString2(unsigned char *puts)                //發(fā)送一串字符串
{
    for (; *puts != 0;        puts++)  UART2_TxByte(*puts);         //遇到停止符0結(jié)束
}



void        uart1_init(void)
{
        PCON |= 0x80;                //UART0 Double Rate Enable
        SCON = 0x50;                //UART0 set as 10bit , UART0 RX enable
        TMOD &= ~(1<<6);                //Timer1 Set as Timer, 12T
        TMOD = (TMOD & ~0x30) | 0x20;        //Timer1 set as 8 bits auto relaod
        TH1 = T1_TimerReload;                //Load the timer
        TR1  = 1;
        ES  = 1;
        EA = 1;
}



/**********************************************/
void UART0_RCV (void) interrupt 4
{
        if(RI)
        {
                RI = 0;
                RX1_Buffer[uart1_wr] = SBUF;
                if(++uart1_wr >= BUF_LENTH)        uart1_wr = 0;
        }

        if(TI)
        {
                TI = 0;
                B_TI = 1;
        }
}


/**********************************************/

void        uart2_init(void)
{
        AUXR |=  (1 << 3);                //串口2波特率加倍
        S2CON  = (S2CON & 0x3f) | (1<<6);        //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率
        S2CON |= 1 << 4;                //允許串2接收

        AUXR |=  1 << 4;        //baudrate use BRT
        BRT = BRT_Reload;

        IE2 |=  1;                        //允許串口2中斷
}

/**********************************************/

void UART2_RCV (void) interrupt 8
{
        if(RI2)
        {
                CLR_RI2();
                RX2_Buffer[uart2_wr] = S2BUF;
                if(++uart2_wr >= BUF_LENTH)        uart2_wr = 0;
        }

        if(TI2)
        {
                CLR_TI2();
                B_TI2 = 1;
        }
}
/*********************做一次ADC轉(zhuǎn)換 *******************/
unsigned int        adc10_start(unsigned char channel)        //channel = 0~7
{
        unsigned int        adc;
        unsigned char        i;

        ADC_RES = 0;
        ADC_RESL = 0;

        ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;

        i = 150;
        do{
                if(ADC_CONTR & ADC_FLAG)
                {
                        ADC_CONTR &= ~ADC_FLAG;
                        adc = (unsigned int)ADC_RES;
                        adc = (adc << 2) | (ADC_RESL & 3);
                        return        adc;
                }
        }while(--i);        //超時(shí)檢測
        return        1024;
}


/*************** 用戶定義參數(shù) *****************************/

#define MAIN_Fosc                22118400L        //define main clock

#define Baudrate1                9600                //define the baudrate, 如果使用BRT做波特率發(fā)生器,則波特率跟串口2一樣
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define Baudrate2                9600                //define the baudrate2,
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define                BUF_LENTH        10                //定義串口接收緩沖長度

/**********************************************************/

#include        <reg51.h>

sfr AUXR1 = 0xA2;
sfr        AUXR = 0x8E;

sfr S2CON = 0x9A;        //12C5A60S2雙串口系列
sfr S2BUF = 0x9B;        //12C5A60S2雙串口系列
sfr IE2   = 0xAF;        //STC12C5A60S2系列
sfr BRT   = 0x9C;

unsigned char         uart1_wr=0;                //寫指針
unsigned char         uart1_rd=0;                //讀指針
unsigned char         xdata RX1_Buffer[BUF_LENTH];
bit                B_TI;

unsigned char         uart2_wr=0;                //寫指針
unsigned char         uart2_rd=0;                //讀指針
unsigned char         xdata RX2_Buffer[BUF_LENTH];
bit                B_TI2;

sbit p00=P0^0;
sbit p01=P0^1;
sbit p02=P0^2;
sbit p03=P0^3;



sbit tx=P2^0;    //從機(jī)狀態(tài)線
sbit rx=P2^1;    //從機(jī)狀態(tài)線
/****************** 編譯器自動(dòng)生成,用戶請勿修改 ************************************/

#define T1_TimerReload        (256 - MAIN_Fosc / 192 / Baudrate1)                        //Calculate the timer1 reload value        at 12T mode
#define BRT_Reload                (256 - MAIN_Fosc / 12 / 16 / Baudrate2)                //Calculate BRT reload value

#define        TimeOut1                (28800 / (unsigned long)Baudrate1 + 2)
#define        TimeOut2                (28800 / (unsigned long)Baudrate2 + 2)

#define        TI2                                (S2CON & 0x02) != 0
#define        RI2                                (S2CON & 0x01) != 0
#define        CLR_TI2()                S2CON &= ~0x02
#define        CLR_RI2()                S2CON &= ~0x01

/**********************************************************/
/*****************ADC配置*************************/
sfr P1ASF     = 0x9D;        //12C5A60AD/S2系列模擬輸入(AD或LVD)選擇
sfr ADC_CONTR = 0xBC;        //帶AD系列
sfr ADC_RES   = 0xBD;        //帶AD系列
sfr ADC_RESL  = 0xBE;        //帶AD系列

//                                                                7       6      5       4         3      2    1    0   Reset Value
//sfr ADC_CONTR = 0xBC;                ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000        //AD 轉(zhuǎn)換控制寄存器
#define ADC_OFF()        ADC_CONTR = 0
#define ADC_ON                (1 << 7)
#define ADC_90T                (3 << 5)
#define ADC_180T        (2 << 5)
#define ADC_360T        (1 << 5)
#define ADC_540T        0
#define ADC_FLAG        (1 << 4)        //軟件清0
#define ADC_START        (1 << 3)        //自動(dòng)清0
#define ADC_CH0                0
#define ADC_CH1                1
#define ADC_CH2                2
#define ADC_CH3                3
#define ADC_CH4                4
#define ADC_CH5                5
#define ADC_CH6                6
#define ADC_CH7                7
unsigned int        adc10_start(unsigned char channel);        //channel = 0~7
double adc;                        
/********************PWM******************************/
#define                PCA_IDLE_DISABLE        0                //1: MCU在IDLE模式時(shí)禁止PCA工作。        0:  MCU在IDLE模式時(shí)允許PCA工作。
#define                PCA_SOURCE_SELECT        4                //選擇PCA的基準(zhǔn)時(shí)鐘源。
                                                                                //0:系統(tǒng)時(shí)鐘Fosc/12。
                                                                                //1:系統(tǒng)時(shí)鐘Fosc/2。
                                                                                //2:定時(shí)器0的溢出。
                                                                                //3:ECI/P3.4腳的外部時(shí)鐘輸入(最大=Fosc/2)。
                                                                                //4:系統(tǒng)時(shí)鐘Fosc。
                                                                                //5:系統(tǒng)時(shí)鐘Fosc/4。
                                                                                //6:系統(tǒng)時(shí)鐘Fosc/6。
                                                                                //7:系統(tǒng)時(shí)鐘Fosc/8。
sfr CCON = 0xD8;
sfr CMOD = 0xD9;
//sfr CCAPM0 = 0xDA;        //PCA module 0 work mode
sfr CCAPM1 = 0xDB;        //PCA module 1 work mode
sfr CL     = 0xE9;        //PCA counter
//sfr CCAP0L = 0xEA;        //PCA模塊0的捕捉/比較寄存器低8位。
sfr CCAP1L = 0xEB;        //PCA模塊1的捕捉/比較寄存器低8位。
//sfr PCA_PWM0 = 0xF2;        //PCA模塊0 PWM寄存器。
sfr PCA_PWM1 = 0xF3;        //PCA模塊1 PWM寄存器。
sfr CH     = 0xF9;
//sfr CCAP0H = 0xFA;                //PCA模塊0的捕捉/比較寄存器高8位。
sfr CCAP1H = 0xFB;                //PCA模塊1的捕捉/比較寄存器高8位。

//sbit CCF0  = CCON^0;        //PCA 模塊0中斷標(biāo)志,由硬件置位,必須由軟件清0。
sbit CCF1  = CCON^1;        //PCA 模塊1中斷標(biāo)志,由硬件置位,必須由軟件清0。
sbit CR    = CCON^6;        //1: 允許PCA計(jì)數(shù)器計(jì)數(shù),必須由軟件清0。
sbit CF    = CCON^7;        //PCA計(jì)數(shù)器溢出(CH,CL由FFFFH變?yōu)?000H)標(biāo)志。PCA計(jì)數(shù)器溢出后由硬件置位,必須由軟件清0。

//#define                PWM0_NORMAL()        PCA_PWM0 = 0        //PWM0正常輸出(默認(rèn))
//#define                PWM0_OUT_0()        PCA_PWM0 = 3        //PWM0一直輸出0
#define                PWM1_NORMAL()        PCA_PWM1 = 0        //PWM1正常輸出(默認(rèn))
#define                PWM1_OUT_0()        PCA_PWM1 = 3        //PWM1一直輸出0


/******************** 本地函數(shù)聲明 ***************/
void        uart1_init(void);
void        uart2_init(void);
void        UART1_TxByte(unsigned char dat);
void        UART2_TxByte(unsigned char dat);
void        PrintString1(unsigned char  *puts);
void        PrintString2(unsigned char  *puts);
unsigned int adc10_start(unsigned char channel);


void        main(void)
{
    unsigned char adc_i,adc_result[6],adc_s;
        unsigned int adc_j;
        /*******PWM***************/
        unsigned char pwm1,pwm0;
        unsigned int pwm_i;
        /*******ADC配置***********/
        double adc;
        P1ASF = 0XE7;//0xff;                        
        ADC_CONTR = ADC_360T | ADC_ON;//只選擇p10 若是所以選ADC_ON;
        /********************PWM配置*****************************/
        //pwm0 = 0;                        // PWM0 初始值
        pwm1 = 0;                        // PWM1 初始值
        
        //CCAP0H = pwm0;                //set PWM wide
        //CCAPM0 = 0x42;                //0x42 Setup PCA module 0 in PWM mode
        
        CCAP1H = pwm1;                //set PWM wide
        CCAPM1 = 0x42;                //0x42 Setup PCA module 1 in PWM mode

        CMOD = (PCA_IDLE_DISABLE << 7) | (PCA_SOURCE_SELECT << 1);        //初始化PCA模式寄存器。
        CL = 0x00;                //clear PCA counter
        CH = 0x00;
        CR = 1;                        //Start PCA counter
        /********************************************************/

//        AUXR |=  0x01;                //串口1使用獨(dú)立波特率發(fā)生器, 波特率跟串口2一樣
//        AUXR1 |= (1<<4);        //將UART2從P1口切換到 RXD2--P1.2切換到P4.2   TXD2---P1.3切換到P4.3
        
        uart1_init();
        uart2_init();

        
        while(1)
        {
            //PWM
        pwm1+=2;
            CCAP1H = pwm1;                //set PWM wide
                //ADC
            //for(adc_i=0; adc_i<8; adc_i++){ //8路ADC  
                adc_j = adc10_start(0/*adc_i*/);
                adc=(double)adc_j/2.048;
                adc_result[0]='A';
                adc_result[1]=(int)adc/1000 + '0';
                adc_result[2]=(int)adc%1000/100 + '0';
                adc_result[3]='.';
                adc_result[4]=(int)adc%100/10 + '0';
                adc_result[5]=(int)adc%10 + '0';
            //}
                for(adc_s=0;adc_s<6;adc_s++){
                UART1_TxByte((char)adc_result[adc_s]);
                }
               
                if((uart1_rd != uart1_wr)&&RX1_Buffer[0]=='1')        //串口0轉(zhuǎn)發(fā)
                {
                        UART2_TxByte(RX1_Buffer[uart1_rd]);
                        if(++uart1_rd >= BUF_LENTH)                uart1_rd = 0;
                }else if((uart1_rd !=10 /*uart1_wr*/)&&RX1_Buffer[0]=='L'&&tx==0)        //串口0轉(zhuǎn)發(fā)
                {
                     rx=1;                                                           //從機(jī)開始執(zhí)行,主機(jī)等待
                         if(RX1_Buffer[1]=='1'){
                 p00=1;}else  {p00=0;}
                         if(RX1_Buffer[2]=='1'){
                         p01=1;}else  {p01=0;}         
                         if(RX1_Buffer[3]=='1'){
                         p02=1;}else  {p02=0;}
                         if(RX1_Buffer[4]=='1'){
                         p03=1; }else  {p03=0;}
                    UART2_TxByte(RX1_Buffer[uart1_rd]);
                        if(++uart1_rd >= BUF_LENTH)                uart1_rd = 0;
                        rx=0;                                                           //從機(jī)已執(zhí)行完
                }
               
                if(uart2_rd != uart2_wr)        //串口2轉(zhuǎn)發(fā)
                {
                        //UART1_TxByte(RX2_Buffer[uart2_rd]);
                        if(++uart2_rd >= BUF_LENTH)                uart2_rd = 0;
                }  
               
        }
}

void        UART1_TxByte(unsigned char dat)
{
        B_TI = 0;
        SBUF = dat;
        while(!B_TI);
        B_TI = 0;
}

void        UART2_TxByte(unsigned char dat)
{
        B_TI2 = 0;
        S2BUF = dat;
        while(!B_TI2);
        B_TI2 = 0;
}

void PrintString1(unsigned char  *puts)                //發(fā)送一串字符串
{
    for (; *puts != 0;        puts++)  UART1_TxByte(*puts);         //遇到停止符0結(jié)束
}

void PrintString2(unsigned char  *puts)                //發(fā)送一串字符串
{
    for (; *puts != 0;        puts++)  UART2_TxByte(*puts);         //遇到停止符0結(jié)束
}


void        uart1_init(void)
{
        PCON |= 0x80;                //UART0 Double Rate Enable
        SCON = 0x50;                //UART0 set as 10bit , UART0 RX enable
        TMOD &= ~(1<<6);                //Timer1 Set as Timer, 12T
        TMOD = (TMOD & ~0x30) | 0x20;        //Timer1 set as 8 bits auto relaod
        TH1 = T1_TimerReload;                //Load the timer
        TR1  = 1;
        ES  = 1;
        EA = 1;
}



/**********************************************/
void UART0_RCV (void) interrupt 4
{
        if(RI)
        {
                RI = 0;
                RX1_Buffer[uart1_wr] = SBUF;
                if(++uart1_wr >= BUF_LENTH)        uart1_wr = 0;
        }

        if(TI)
        {
                TI = 0;
                B_TI = 1;
        }
}


/**********************************************/
void        uart2_init(void)
{
        AUXR |=  (1 << 3);                //串口2波特率加倍
        S2CON  = (S2CON & 0x3f) | (1<<6);        //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率
        S2CON |= 1 << 4;                //允許串2接收

        AUXR |=  1 << 4;        //baudrate use BRT
        BRT = BRT_Reload;

        IE2 |=  1;                        //允許串口2中斷
}

/**********************************************/         
void UART2_RCV (void) interrupt 8
{
        if(RI2)
        {
                CLR_RI2();
                RX2_Buffer[uart2_wr] = S2BUF;
                if(++uart2_wr >= BUF_LENTH)        uart2_wr = 0;
        }

        if(TI2)
        {
                CLR_TI2();
                B_TI2 = 1;
        }
}
/*********************做一次ADC轉(zhuǎn)換 *******************/
unsigned int        adc10_start(unsigned char channel)        //channel = 0~7
{
        unsigned int        adc;
        unsigned char        i;

        ADC_RES = 0;
        ADC_RESL = 0;

        ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;

        i = 150;
        do{
                if(ADC_CONTR & ADC_FLAG)
                {
                        ADC_CONTR &= ~ADC_FLAG;
                        adc = (unsigned int)ADC_RES;
                        adc = (adc << 2) | (ADC_RESL & 3);
                        return        adc;
                }
        }while(--i);        //超時(shí)檢測
        return        1024;
}

評分

參與人數(shù) 3黑幣 +75 收起 理由
wpppmlah + 15 很給力!
高高的白楊 + 10 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:884711 發(fā)表于 2022-8-9 05:58 | 只看該作者
看起來很高大上,學(xué)習(xí)一下,謝謝分享!
回復(fù)

使用道具 舉報(bào)

板凳
ID:1006306 發(fā)表于 2022-8-9 08:50 | 只看該作者
有意思,目前51的速度不夠,使用片上資源時(shí)候存在延遲;
如果這樣玩,感覺兩塊單片機(jī)各干個(gè)的比較好,然后通過SPI通訊,速度快點(diǎn):比如一個(gè)負(fù)責(zé)顯示、一個(gè)負(fù)責(zé)ADC等
為什么呢,如要做使用一個(gè)高精度的24位ADC,一般的都比較貴,但是用TM7711這種一塊錢的,速度又很慢,雙核也能解決速度慢影響其他代碼運(yùn)行問題。
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表