|
發布時間: 2018-1-15 09:56
正文摘要:STC15的ADC結果控制PWM輸出,關系曲線如下,請問各位大神,如何建立兩者的關系,用關系式的話用什么樣的關系式運行速度會快一些,謝謝! |
| 我這陣子也在琢磨PWM頻率怎么等于adc轉化結果,我用的stc8,PWM八位,ADC12位 |
村風 發表于 2018-1-18 12:52 /*********************主函數**************************/ void main() { ADC_init(); //ADC初始化 PWM_init(); //PWM初始化 while(1) { ADC_Value(); //ADC結果賦值 LED_display(); //led顯示 Update_PWM(); //PWM輸出 } } /****************************************************/ /************************ADC初始化函數*********************/ void ADC_init() { P1M1=0x20; P1M0=0; //I/O口模式為P1.5僅為輸入(高阻),作為A/D使用,P1其他口為準雙向 //P1.1為準雙向口,作為PWM使用 P1ASF=0x20; //設置P1.5端口為模擬輸入 CLK_DIV=0x00; // MCK0_S1=0, MCK0_S1=0 : 主時鐘不對外輸出時鐘 //ADRJ=0 :10位A/D轉換結果的高8位存放于ADC_RES中,低2位存放于ADC_RESL的低2位中; //Tx_Rx=0 :串口1為正常工作方式 //CLKS2=0 , CLKS1=0 , CLKS0=0 :主時鐘頻率/1,不分頻 ADC_RES = 0; //清除之前ADC結果 ADC_RESL = 0; //清除之前ADC結果 ADC_CONTR = ADC_POWER | ADC_SPEEDLL; //ADC電源打開; //轉換速度:540個時鐘周期 delay(2); //延時,等待ADC_CONTR設置完成 } /********************************************************/ /******************獲取ADC結果**********************/ uchar Get_ADC_result() { uchar ch = 5; //模擬輸入通道號5(P1.5) ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START; //ADC電源打開;轉換速度:540個時鐘周期 //模擬輸入通道P1.5;ADC開始 _nop_(); _nop_(); _nop_(); _nop_(); //等待ADC_CONTR設置完成 while(!(ADC_CONTR&ADC_FLAG)); //等待ADC結束標志位置1 ADC_CONTR &= ~ADC_FLAG; //關閉ADC return ADC_RES; //返回ADC結果 } /**************************************************/ /*******************ADC結果賦值*******************/ void ADC_Value() { adc = Get_ADC_result(); //ADC結果賦值 } /****************************************************/ /******************PWM初始化***********************/ void PWM_init() { ACC = P_SW1; ACC &= ~( CCP_S0 | CCP_S1 ); //將P_SW1的運算結果放入累加器 P_SW1 = ACC; //CCP在(P1.2/ECI,P1.1/CCP0,P1.0/CCP1,P3.7/CCP2) CCON = 0x00; //PCA定時器停止運行, //PCA計數器溢出標志位CF清零, //模塊中斷標志位清零 CMOD = 0x02; //空閑模式PCA計數器繼續工作 //PCA計數器時鐘源:系統時鐘頻率SYSclk/2 //禁止PCA計數器中斷使能(計數器CCON中CF位) PCA_PWM0 = 0x00; //PCA模塊0工作在8位PWM } /**************************************************/ /********************PCA計數器復位***********************/ void PCA_reset() { CL = 0x00; CH = 0x00; //重置PCA計數器 } /**************************************************/ /*********************PWM更新**********************/ void Update_PWM() { if(adc <= 11) { //PWM0輸出占空比(100H-CCAP0L)/100H) PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 17; //PWM0輸出占空比(100H-CCAP0L)/100H) CCAPM0 = 0x42; //PCA比較/捕獲寄存器模塊0(P1.1)允許比較器功能 //工作在PWM模式 CR = 1; //PCA計數器開始運行 } if(adc > 11 && adc <= 22) // { PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 9.6 * adc - 54; // CCAPM0 = 0x42; CR = 1; } if(adc > 22 && adc <= 35) { PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 1.19 * adc + 132; // CCAPM0 = 0x42; CR = 1; } if(adc > 35 && adc <= 68) { PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 0.33 * adc + 163; // CCAPM0 = 0x42; CR = 1; } if(adc > 68 && adc <= 108) { PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 0.106 * adc + 178.6; // CCAPM0 = 0x42; CR = 1; } if(adc > 108) { PCA_reset(); //PCA計數器復位 CCAP0H = CCAP0L = 165; // CCAPM0 = 0x42; CR = 1; } } /*****************************************************/ 這是我寫的程序,求幫我看一下 |
村風 發表于 2018-1-18 12:52 按照你說的做的分段的直線方程式輸出大致上吻合,但是一直存在一個問題,就是在中間有幾個電壓點不穩定,會有來回跳動的現象,是不是我設置的PWM頻率不對,還是可能的其他原因。像這樣 PWM應該用多少頻率,我用的是系統時鐘頻率SYSclk/2,8位的PWM。 |
chenshui7601 發表于 2018-1-17 11:22 你這個本身就是非線性的,ADC和PWM本身也不是完全的非線性,要做到這個曲線,說明在某段區間的增量不同,通過軟件參數分段調節就可以達到所需要求,另外如果用積分電路去平滑PWM,還要考慮元器件本身的惰性和電壓電流慣性,遲滯性問題,我說的只是一種方法,僅供參考。 |
村風 發表于 2018-1-15 12:35 因為AD采樣的值直接賦給PWM輸出的電壓值跟需要的不一致,滿足上面的曲線關系,電壓才能滿足需要。 |