欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2753|回復(fù): 0
收起左側(cè)

STC12C5A60S2利用PCA時(shí)鐘溢出做的PWM信號(hào) 0-255 資料共享 不對(duì)的地方望大家修改共享

[復(fù)制鏈接]
ID:254747 發(fā)表于 2019-11-11 20:06 | 顯示全部樓層 |閱讀模式
1.  程序里面想詳細(xì)的算法 思路,
2. 在晶振和CPU滿足計(jì)算的情況下,理論是你要多少你就通過(guò)編碼器調(diào)節(jié)多少
3. 本程序任意頻率調(diào)試是通過(guò)編碼器來(lái)切換的,
4.關(guān)于精度問(wèn)題 在100hz內(nèi)非常準(zhǔn),在最大255HZ的時(shí)候相差20hz左右,  問(wèn)題可能出現(xiàn)在 定時(shí)器計(jì)數(shù)這個(gè)位置, 我全部取整數(shù)了 所以誤差比較大
  如果計(jì)數(shù)的出來(lái)本來(lái)機(jī)是整數(shù)的,那頻率相對(duì)準(zhǔn)確的, 在100hz的時(shí)候就是標(biāo)準(zhǔn)的100hz

注意看頻率

注意看頻率
IMG20191111200204.jpg

單片機(jī)源程序如下:
/*------------------------------------------------------------------*/
/* --- 功能  pwm輸出 頻率可調(diào) -------------------------- -----------*/
/* --- STC12C5Axx                                            -------*/
/* --- 對(duì)于定時(shí)器選擇的時(shí)候,應(yīng)該選擇16位---------------------------*/
/* --- 不應(yīng)該選擇16位自動(dòng)重裝,因?yàn)?6位自動(dòng)重的工作原理是當(dāng)TL0------*/
/* --- 溢出的時(shí)候,會(huì)直接把TH0的值填充到TL0里面計(jì)算這樣就會(huì)導(dǎo)致-----*/
/* --- PWM計(jì)算頻率出錯(cuò)     -----------------------------------------*/
/* --- 定時(shí)的工作方式為。定時(shí)器0的工作模式為16位--------------------*/
/* 計(jì)算方法 例如12MHZ需要轉(zhuǎn)化為300HZ,那么根據(jù)上圖,首先我們需要確定
PCA時(shí)鐘輸入頻率,根據(jù)公式 300*256=76800HZ,這個(gè)值就是我們需要的PCA時(shí)
鐘輸入頻率。現(xiàn)在問(wèn)題就是 ,我們?cè)趺窗?2MHZ,轉(zhuǎn)化為76.8KHZ,
12000KHZ/76.8KHZ=156.25  ,這個(gè)156.25就是分頻基數(shù),而這個(gè)分頻基數(shù)由
我們的定時(shí)器溢出參數(shù)來(lái)設(shè)定,意思就是當(dāng)我們定時(shí)器如果計(jì)數(shù)156.25溢出就
可以做到分頻基數(shù)為156.25, 所以我們?cè)谠O(shè)置定時(shí)器0的計(jì)數(shù)起始值就
是65536-156=65380,對(duì)應(yīng)TH0=0XFF,TL0=0X64。    0XFF=255   0X64=100
初始是如何分離的計(jì)算方法 65380/256=255 ps:取的整數(shù),然后用255*256=65280
再用65380-65280=100這個(gè)就是 65380對(duì)256求于的個(gè)數(shù)放在TL0里面也就是0X64
那么TH0就應(yīng)該放255將255轉(zhuǎn)化為16進(jìn)制數(shù)為0xff   */
/*整體計(jì)算公式(65536-12000/300*256)/256
/* article, please specify in which data and procedures from STC    */
/*------------------------------------------------------------------*/
/*按鍵k1  k2  分別接在 P0^6 P^7口  用的是獨(dú)立鍵盤*/
/*實(shí)現(xiàn)的功能是,控制CR的開(kāi)通和關(guān)斷來(lái)實(shí)現(xiàn)混頻效果*/
/*第二次修改時(shí)間2019-10-6*/
/*作者 Alan*/


#include <STC12C5A60S2.H>
#include <stdint.h>
//#include <intrins.h>
#define FOSC 18432000

/*分別定義了兩個(gè)不高低位的變量用于保存 定時(shí)器初值,從而初值計(jì)算里面帶變量計(jì)算以后保存到這個(gè)變量 這時(shí)候就能在中斷正常重新裝初值了,也不會(huì)出錯(cuò)*/
uint8_t  TH,TL;      

/*上一次的狀態(tài)*/
uint8_t  Last_Amb_Status =  0;        

/*該變量用于保存按鍵值*/
uint8_t  Sd_Key_Value    =  0;

uint8_t  Sd_Key_Value2    =  0;        


/*編碼器三個(gè)I/O的定義 分別為,A口 B口 sdKey */
sbit  Pin_Portry_A=P2^4 ;
sbit  Pin_Portry_B=P2^3 ;     
sbit  Pin_Portry_Sd=P2^2 ;

/*testing 測(cè)試端口 暫時(shí)不用*/
sbit  BUZ = P3^0;

sbit  LED = P3^7;

sbit  k1  = P0^6;

sbit  k2  = P0^7;

sbit  LED_1 = P0^5;


unsigned char flag=0;

uint8_t Data_key2(uint8_t *key_val2);


/*延時(shí)1ms級(jí)函數(shù)2*/

void delay(unsigned int z)
{
        unsigned int  x,y;
        for(x=z;x>0;x--)
                for(y=135;y>0;y--);

}


/*副頻自動(dòng)變化*/          //有缺陷 放棄  重新構(gòu)思    但是這里取消了  不影響主頻哈     

void fuping_bianhua(uint8_t XHZ)
{
       uint8_t i;
         for(i=0;i<XHZ;i++)
          {
            CR = 1;
                delay(25);   
            CR = 0;
                delay(25);
           }         
}

/*旋轉(zhuǎn)編碼器調(diào)整副頻*/

uint8_t Data_key2(uint8_t *key_val2)             //*key_val這個(gè)是一個(gè)指針嗎  
{
    //這個(gè)counter是為了防止沒(méi)有鍵值動(dòng)作時(shí),程序一直在這里等待
    //具體的等待時(shí)間應(yīng)該根據(jù)編碼開(kāi)關(guān)的脈沖周期和程序的執(zhí)行周期來(lái)確定
    //可以根據(jù)實(shí)際情況進(jìn)行調(diào)整,連續(xù)測(cè)試的時(shí)候,可以先去掉此限定條件
    uint16_t wait_counter = 100000;          //counter等待的時(shí)間

        uint8_t temp_key_val2 = *key_val2;  
                                                        //temp_key_val 這個(gè)是char型的變量 最大255 所以不需要設(shè)置最大值

        Last_Amb_Status = Pin_Portry_A;            //保存采樣前的A口狀態(tài)

        //開(kāi)始采樣端口A的跳變邊沿,如果沒(méi)有產(chǎn)生跳變
        //A口的當(dāng)前采樣值和之前保存的值是一樣的,異或后值為0
        //while持續(xù)等待兩個(gè)值不同時(shí),跳過(guò)while執(zhí)行下一步驟,如果等待到wait counter為0 的時(shí)候就跳出,然后執(zhí)行下一步;


        while( !(Pin_Portry_A ^ Last_Amb_Status) && --wait_counter);



        if(!wait_counter)  //在while語(yǔ)句期間  如果A口發(fā)生變化 除了跳出 while 同時(shí)也跳過(guò)這里 這里不能打冒號(hào)
         

        
        return  0;           //跳過(guò)這里


        //此時(shí)采樣B口的電平
        //如果B口的值和采樣A口跳變沿之前的值相同,判斷為順時(shí)針旋轉(zhuǎn)
        //如果B口的值和采樣A口跳變沿之前的值不同,判斷為逆時(shí)針旋轉(zhuǎn)


        
        if(!(Pin_Portry_B ^ Last_Amb_Status))
        {
           //順時(shí)針旋轉(zhuǎn)
            temp_key_val2++;



                  if(temp_key_val2 < 2)
                     
                         temp_key_val2 = 2;

                  if(temp_key_val2 > 40);  //如果大于40就截止  限制最大
                     
                         temp_key_val2 = 2;         //重新設(shè)置為2

                        *key_val2 = temp_key_val2;  

               
                  return  1;
           }
            
        else if(Pin_Portry_B ^ Last_Amb_Status)          //和上面正轉(zhuǎn)工作過(guò)程一樣          zc注釋
        {
           
            //逆時(shí)針旋轉(zhuǎn)
            temp_key_val2--;

                if(temp_key_val2 > 40)  //如果逆時(shí)針大于40就截止
                     
                temp_key_val2 = 2;           //重新設(shè)置為2

                if(temp_key_val2 <= 2)          //如果小于2 就設(shè)置為最大40

                        temp_key_val2 = 40;

                        *key_val2 = temp_key_val2;

                  return  1;
        }

        return 0;
}



/* 定時(shí)器配置與初始化*/
void   Timer0Init(void)
{

    /*定義一個(gè)32位整形變量 temp 存放編碼器初值*/
        uint32_t temp = 5;

        /*設(shè)置定時(shí)器0位1T模式*/
        /*先將tmod高4位保存為1 “TMOD=$=0XF0”,這樣是防止多個(gè)定時(shí)器使用的時(shí)候,直接賦值導(dǎo)致其它定時(shí)器工作異常,或者是各定時(shí)器無(wú)法突出自己的作用*/
        /*通過(guò)上面保存了高4位后,接下來(lái)進(jìn)行或運(yùn)算"TMOD=|=0X01",從而只是將我們需要的位打開(kāi)其它全部關(guān)閉,這樣非常穩(wěn)妥,互補(bǔ)相干*/
        AUXR |= 0x80;               
        TMOD &= 0xF0;               
        TMOD |= 0x01;
                        
        /*把要記的次數(shù),通過(guò)下面的運(yùn)算,算出來(lái)以后,保存到temp里面,供定時(shí)器裝初值用*/
        temp = 0x10000-(18432000/(temp*256));

        /*temp內(nèi)部保存的次數(shù),分別裝在定時(shí)器的高8位和低8位*/
        TH0  = TH = temp / 256;               
        TL0  = TL = temp % 256;                //設(shè)置定時(shí)器初值

        /*啟動(dòng)定時(shí)器相關(guān)功能,清楚標(biāo)志位,啟動(dòng)定時(shí)器TR0,開(kāi)總中斷,開(kāi)定時(shí)器中斷ET0*/
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時(shí)器0開(kāi)始計(jì)時(shí)
        EA=1;
        ET0=1;



}

        /*對(duì)key函數(shù)聲明*/
    uint8_t Data_key(uint8_t *key_val);

        /*對(duì)頻率更新函數(shù)聲明*/
    void pinglvgengxing(uint8_t key_val);


void main(void)

{



        Timer0Init();         //初始化定時(shí)器配置函數(shù)

    CCON = 0;
    CL = 0;
    CH = 0;

    /*將PCA fosc模式設(shè)置為 定時(shí)器0溢出率*/
    CMOD = 0x04;

        /*setting CCAP0H 脈寬為50%輸出*/
    CCAP0H = CCAP0L = 0x80;   
              
        /*setting PCA模式為8bit自動(dòng)重裝模式*/
    CCAPM0 = 0x42;
                        
           /*setting CCAP1H 脈寬為50%輸出*/
    CCAP1H = CCAP1L = 0x80;        

    PCA_PWM1 = 0x00;

        /*setting PCA模式為8bit自動(dòng)重裝模式*/
    CCAPM1 = 0x42;

        /*PCA時(shí)鐘開(kāi)始運(yùn)行,計(jì)數(shù), 輸出pwm信號(hào)*/
    CR = 1;                        
        

  while (1)
        {        

            

          if(0 == flag)
         {
                LED=0;
               if(Data_key(&Sd_Key_Value));

                else if(Pin_Portry_Sd!=1)          // 判斷按鍵是否被按下
               {
                        
                                
                           delay(5);           //消抖動(dòng)

                       if(Pin_Portry_Sd!=1)  //再次判斷

                              while(!Pin_Portry_Sd);

                                 LED=1;
                                    flag=1;
                          
                   }
          }
                        
                 else  if(1 == flag)
                   {
                                   LED_1=0;
                        if(Data_key2(&Sd_Key_Value2));
                                 
                        if(Pin_Portry_Sd!=1)  //再次判斷
                                {
                                 delay(5);

                                while(!Pin_Portry_Sd);
                                  LED_1=1;
                                    flag=0;
                                 }
                        
                 }

         
                  
                        fuping_bianhua(Sd_Key_Value2);



                   // 如果要在1602上顯示對(duì)應(yīng)的頻率,直接將“Sd_Key_Value2”變化寫數(shù)據(jù)到1602
                   //記住要分離式數(shù)據(jù)哦   這個(gè)設(shè)計(jì)是0-255HZ  誤差有點(diǎn)大 開(kāi)到255的時(shí)候頻率誤差在20-30hz
                   //這個(gè)誤差主要是來(lái)自PCA時(shí)鐘運(yùn)算這里,主要是計(jì)算的時(shí)候出現(xiàn)了小數(shù)點(diǎn)就省略了 如果從新
                   //將小數(shù)點(diǎn)保留 頻率是很準(zhǔn)的   在100hz內(nèi)的頻率基本就很準(zhǔn)的  自己去調(diào)整吧

                 
                        pinglvgengxing(Sd_Key_Value);
               

   }

}


/*頻率更新函數(shù)*/
void pinglvgengxing(uint8_t key_val)
{
        uint32_t temp;
        //關(guān)閉定時(shí)器中斷
        //關(guān)閉全局中斷
        //失能定時(shí)器
        //清除定時(shí)器溢出標(biāo)志位
        ET0 = 0;
        EA  = 0;
        TR0 = 0;
        TF0 = 0;

        //重新初始化定時(shí)初值
        temp = 0x10000-18432000/(key_val*256) ;
        TH0 =TH= temp/256;                //設(shè)置定時(shí)初值
        TL0 =TL= temp%256;                //設(shè)置定時(shí)初值

        //開(kāi)啟全局中斷
        //開(kāi)啟定時(shí)器中斷
        //使能定時(shí)器
        EA  = 1;
        ET0 = 1;
        TR0 = 1;
}


/*主頻按鍵函數(shù)*/
uint8_t Data_key(uint8_t *key_val)             //*key_val這個(gè)是一個(gè)指針嗎  
{
    //這個(gè)counter是為了防止沒(méi)有鍵值動(dòng)作時(shí),程序一直在這里等待
    //具體的等待時(shí)間應(yīng)該根據(jù)編碼開(kāi)關(guān)的脈沖周期和程序的執(zhí)行周期來(lái)確定
    //可以根據(jù)實(shí)際情況進(jìn)行調(diào)整,連續(xù)測(cè)試的時(shí)候,可以先去掉此限定條件
    uint16_t wait_counter = 100000;          //counter等待的時(shí)間

        uint8_t temp_key_val = *key_val;  //這個(gè)是一個(gè)指針變量嗎?  如果是  那它是指向 (Sd_Key_Value) 這里面的嗎     //我還沒(méi)有學(xué)過(guò)指針哈哈哈

        /*把A口的值保存到當(dāng)前狀態(tài) 變量里面*/  
        Last_Amb_Status = Pin_Portry_A;            //保存采樣前的A口狀態(tài)

        //開(kāi)始采樣端口A的跳變邊沿,如果沒(méi)有產(chǎn)生跳變
        //A口的當(dāng)前采樣值和之前保存的值是一樣的,異或后值為0
        //while持續(xù)等待兩個(gè)值不同時(shí),跳過(guò)while執(zhí)行下一步驟,如果等待到wait counter為0 的時(shí)候就跳出,然后執(zhí)行下一步;


        while( !(Pin_Portry_A ^ Last_Amb_Status) && --wait_counter);



        if(!wait_counter)  //在while語(yǔ)句期間  如果A口發(fā)生變化 除了跳出 while 同時(shí)也跳過(guò)這里 這里不能打冒號(hào)
         


        return  0;           //跳過(guò)這里


        //此時(shí)采樣B口的電平
        //如果B口的值和采樣A口跳變沿之前的值相同,判斷為順時(shí)針旋轉(zhuǎn)
        //如果B口的值和采樣A口跳變沿之前的值不同,判斷為逆時(shí)針旋轉(zhuǎn)


        
        if(!(Pin_Portry_B ^ Last_Amb_Status))
        {
           //順時(shí)針旋轉(zhuǎn)
            temp_key_val++;


               
                  if(temp_key_val < 5)
                     
                         temp_key_val = 5;

                          //if(temp_key_val > 40)  //如果大于40就截止
                     
                        // temp_key_val = 2;         //重新設(shè)置為2

                 //我感覺(jué)這個(gè)是一個(gè)指針變量  將按鍵值傳遞給指針 然后指針指向Sd_Key_Value地址 然后就可以將 temp_key_val;結(jié)果傳遞給Sd_Key_Value
                        *key_val = temp_key_val;  

               
                  return  1;
           }
            
        else if(Pin_Portry_B ^ Last_Amb_Status)          //和上面正轉(zhuǎn)工作過(guò)程一樣          zc注釋
        {
            //逆時(shí)針旋轉(zhuǎn)

               
                 temp_key_val--;

            //        if(temp_key_val2 > 40)  //如果逆時(shí)針大于40就截止
                     
              //        temp_key_val2 = 2;           //重新設(shè)置為2

                     if(temp_key_val <= 5)   

                         temp_key_val =255;            //限制最小  

               
                        *key_val = temp_key_val;
               
                  return  1;
                 
        }
        
         
        return 0;
}




/*定時(shí)器0中斷*/
void tm0_isr(void) interrupt 1 using 1
{
     TH0 =TH;                //設(shè)置定時(shí)初值
     TL0 =TL;                //設(shè)置定時(shí)初值
}

以上程序51hei下載地址:
通過(guò)編碼器開(kāi)關(guān)來(lái)控制 混頻程序V1.0.rar (37.77 KB, 下載次數(shù): 18)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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