久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6735|回復: 53
收起左側

PIC單片機輸出不了占空比50%的方波——幫扶一把學單片機的60后

  [復制鏈接]
ID:27513 發表于 2021-11-24 11:18 | 顯示全部樓層 |閱讀模式
自我介紹下:60后從業模電,自封工程師,動手能力強。學單片機歷程30年,學級仍是未入門的學前班。所以各位看官都是我的老師,各位的每句話都能使我進步!期望大家都出一份正能量!廢話不說入正題:
PIC12F683單片機,編程平臺MPLAB IDE -V8.84  編譯器HI-TECH-PICC_9.83
無單片機開發板,有RF809H編程器,有GA1202CAL示波器
實驗要求單片機GP0和GP1輸出20KHz占空比為50%的互補方波

C程序:
#include <pic.h>

void IO_init(void) /*端口初始化*/
        {
                TRISIO=0x00;
                GPIO=0X00;
        }
void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
        {
                T0CS=0;    //timer0工作于定時器方式
                PSA=1;     //timer0不分頻
                T0IF=0;    //清timer0中斷標志
                TMR0=0xE0; /*置初值 20KHz的半個周期為25us*/
                T0IE=1;    //timer0中斷允許
                GIE=1;     //開全局中斷
        }

        void interrupt isr(void)   //中斷子程序
                {
                        TMR0=0xE0; //定時器0置初值25us
                        T0IF=0;    //清中斷標志
                        GP0=~GP0;  //GP0位取反
                        GP1=!GP0;  //使GP1引腳取反GP0
                        /*在這里廢寢忘食3總天,一度引起孫子的奶奶發飆
                                也沒有折騰出正確的結果*/                                 
                }  
void main(void)          //主程序
        {
        
                IO_init();         //引腳初始化函數
                timer0_init();     //定時器0初始化函數
        
                while(1)    //死循環
                {
               
                        
                }
                        
        }

寫入單片機;手工搭建最小系統上示波器看波形結果頻率是26.3KHz,GP0引腳正占空比只有12.6%,負占空比87.3%;GP1引腳正占空比86.3%,負占空比13.6%幅值5.04V
刪除中斷子程序里的GP1=!GP0語句結果GP0引腳示波器上只有一條5.17V的直線沒有波形了,頻率顯示為小于10Hz.
大家說怪不怪。”緫揋P0輸出信號不受影響的怎么就沒有了呢????
接下來就是折騰了反復換TMR0的初值,最后試到0xE0時頻率是19.96KHz正占空比9.6%負占空比是90.4%,也就是說正脈沖的寬度是4.8us這個值基本是恒定的試了下,從10KHz到30KHz這個值不變.然后大發現這個4.8us竟然是執行GP1=!GP0 這條語句所耗費的時間,所以上述刪除這條語句示波器上只顯示一直線。


GAS0002副本.jpg
回復

使用道具 舉報

ID:27513 發表于 2021-11-24 11:31 | 顯示全部樓層
本帖最后由 xxll 于 2021-11-24 12:03 編輯

現在的問題就是怎樣才能使正負波形占空比為50%  ?

于是我又timer2這個定時器來做程序如下:
#include <pic.h>
#define uchar unsigned char
#define uint  unsigned int
        uchar TA,TB;
void IO_init(void) /*端口初始化*/
        {

                TRISIO=0x00;
               
        }
void timer2_init(void) //fosc/4   8M所以計數周期為0.5us
        {
                T2CON=0b00000101;        //timer2控制寄存器設置        
                PR2=24;        //25us比較數字
                PEIE=1;        //模塊中斷使能
                TMR2IE=1;                //定時器2中斷使能
                GIE=1;       //        開全局中斷
        }

        void interrupt isr(void)
                {
                        GP1=~GP1;//中斷后設引腳反相
                        GP0=~GP1;//使GP0與GP1反相                        
                        TMR2IF=0;/*TMR2溢出標志清零*/               
                }  
void main(void)
        {
                __CONFIG(FOSC_INTOSCIO&WDTE_OFF);//系統配置,使用內置時鐘,關看門狗
                OSCCONbits.IRCF0=1;
                OSCCONbits.IRCF1=1;
                OSCCONbits.IRCF2=1;//此3條設置時鐘為8M
                IO_init();//端口初始化
                timer2_init();//timer2初始化
                GPIO=0X00;//全部端口設為0
                while(1)  //死循環
                {
               
                        
                }
                        
        }
GAS0003副本.jpg
回復

使用道具 舉報

ID:624769 發表于 2021-11-24 13:42 | 顯示全部樓層
PIC 沒玩過,本不該發言,但是看你帖子實在冷清,深感年紀大了學單片機之不易……,
作為70后,在你身上看到10年后的自己,所以多多少少想幫你頂一把。
雖然PIC沒有玩過, 有些道理應該是互通的所以說兩句。

                       GP0=~GP0;  //GP0位取反
                        GP1=!GP0;  //使GP1引腳取反GP0
基于單片機的工作原理,這里很可能得不到你希望的結果…… 舉個簡單的例子。
GP0 = ~GP0; 這里的等號左邊 和 等號右邊,其實是不同的東西。
等號的右邊,是當前GP0的電平狀態,綜合了外部電平和內部設置之后的最后結果,然后通過~取反
等號左邊,是你給GP0 設置的新狀態即會改變GP0的內部電平關系,然后通過這個內部關系再去改變端口的外部關系。
當你運行完  GP0 = ~GP0   立刻運行  GP1=!GP0; 此時讀取的 GP0, 如上所說是結合內部設置和外部電平綜合后的一個狀態,而不是你剛剛賦值的結果,由于各種單片機不同我不能說100%,但是有很大的概率,這個時候的GP0,是并沒有完成  GP0 = ~GP0 這個操作后更新 的狀態。 但,也有可能已經完成了更新。這個不好判斷,所以在時序允許的情況下,一般應該這么寫代碼。
                   GP1= GP0;  //使GP1引腳取GP0
                   GP0= !GP0;  //GP0位取反
這樣能保障,兩次讀到的GP0 是相等的。
如果,你一定要先改GP0, 再改GP1 那么也可以用一個中間變量
                   F0 = GP0;
                   GP0 = !F0;
                   GP1 = F0;
這樣是比較安全的操作。
回復

使用道具 舉報

ID:313048 發表于 2021-11-24 13:55 | 顯示全部樓層
本帖最后由 AUG 于 2021-11-24 14:01 編輯
xxll 發表于 2021-11-24 11:31
現在的問題就是怎樣才能使正負波形占空比為50%  ?

于是我又timer2這個定時器來做程序如下:

從你這個圖可以看出,那個脈沖是你每次進去之后GP0=~GP0取反的結果,后面變低是因為你又GP1=!GP0,使其變低了.建議如下操作
void main()
{
timer_init();//25us一次中斷   40KHz
GP0 = 1;  //起始值相反
GP1 = 0;
while(1);
}
interrupt timer(void)
{
//重裝計數值
//清中斷
GP1=GP0;
GP0=~GP0;
}
回復

使用道具 舉報

ID:892596 發表于 2021-11-24 14:18 | 顯示全部樓層
用過一個仿PIC的芯片。
用的T0做的510US定時:
1.jpg
用的T1做的38KHz的方波:
2.jpg
中斷里的IO翻轉。
3.jpg
回復

使用道具 舉報

ID:892596 發表于 2021-11-24 14:19 | 顯示全部樓層
不確定寄存器完全一致的,你可以參考一下,看著修改。
回復

使用道具 舉報

ID:401564 發表于 2021-11-24 14:26 | 顯示全部樓層
中斷程序這樣改試一下:
void interrupt isr(void)   //中斷子程序
                {
                        TMR0=0xE0; //定時器0置初值25us
                        T0IF=0;    //清中斷標志
                        GP1=GP0;  //使GP1引腳取反GP0后的GP0   
                        GP0=~GP0;  //GP0位取反                                                
                }
其它參考意見:
PIC我用過,個人感覺PIC實在不適合單片機入門,更多的是工業產品才用的,很多操作是有嚴格要求的,比如硬件堆棧,甚至很多學單片機的對堆棧也只是百度大概的看一遍,但真正到PIC硬件堆棧的時候,問題就出來了
IO的數據方向要注意,中斷只有一個入口.......
數據手冊是肯定要一邊寫代碼一邊看的,但PIC的8位單片機數據手冊都是匯編的,印象中是沒有C的,所以,匯編指令最好是也要會一點,不要求能寫程序,至少對著指令能看明白

回復

使用道具 舉報

ID:298123 發表于 2021-11-24 15:11 | 顯示全部樓層
一般來說,端口設置和讀取的寄存器是分開的,設置后馬上讀取,單片機速度太快,讀取狀態值不一定是穩定后的值。最好定義個變量 bit status,   中斷里改變status = !status; 然后賦值給端口寄存器
回復

使用道具 舉報

ID:123289 發表于 2021-11-24 15:12 | 顯示全部樓層
增加一個中間變T.
每次中斷后:
GP0=T
T=!T
GP1=T
試試看。
回復

使用道具 舉報

ID:123289 發表于 2021-11-24 15:13 | 顯示全部樓層
如果成功,再告訴你原因。不成功就罷了。
回復

使用道具 舉報

ID:139866 發表于 2021-11-24 15:25 | 顯示全部樓層
90后,來一個最簡單的方法,因為手中沒有示波器,只好麻煩樓主驗證一下了,如果還是不行就自動忽略后面的吧,一般來說對定時器要求較高,定時器中斷里處理的代碼越少越好,能少就盡量少,以下是代碼
  1. #include <pic.h>

  2. char i = 0;

  3. void IO_init(void) /*端口初始化*/
  4. {
  5.         TRISIO=0x00;
  6.         GPIO=0X00;
  7. }
  8. void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
  9. {
  10.         T0CS=0;    //timer0工作于定時器方式
  11.         PSA=1;     //timer0不分頻
  12.         T0IF=0;    //清timer0中斷標志
  13.         TMR0=0x01; /*置初值 20KHz的半個周期為25us*/
  14.         T0IE=1;    //timer0中斷允許
  15.         GIE=1;     //開全局中斷
  16. }

  17. void main()
  18. {
  19.     IO_init();         //引腳初始化函數
  20.     timer0_init();     //定時器0初始化函數
  21.         while()
  22.         {
  23.                 if(i >= 50) {
  24.                         i = 1;
  25.                 }else if(i >= 25) {
  26.                         GP0 = 1;  
  27.                         GP1 = 0;
  28.                 }else if(i >= 0) {
  29.                         GP0 = 0;
  30.                         GP1 = 1;
  31.                 }
  32.         }
  33. }

  34. void interrupt isr(void)   //中斷子程序
  35. {
  36.     TMR0 = 0x01; //定時器0置初值1us
  37.     T0IF = 0;    //清中斷標志                       
  38.         i ++;
  39. }
復制代碼

回復

使用道具 舉報

ID:27513 發表于 2021-11-24 16:38 | 顯示全部樓層
yzwzfyz 發表于 2021-11-24 15:12
增加一個中間變T.
每次中斷后:
GP0=T

首先謝謝你,你這種方法我之前也試過,正脈沖的寬度只增加2.5us
回復

使用道具 舉報

ID:27513 發表于 2021-11-24 17:26 | 顯示全部樓層
188610329 發表于 2021-11-24 13:42
PIC 沒玩過,本不該發言,但是看你帖子實在冷清,深感年紀大了學單片機之不易……,
作為70后,在你身上看 ...

感謝您的參與,你說的第一種GP0=~GP0;GP1=!GP0;剛試過結果脈寬沒有改變.這種順序改變在示波器上觀看沒有變化的.當然,我知道編程是要講究時序的,否則實際應用中會出大問題的!至于第二種方法我在早些時候也試過,中間加一個變量操作,確實增加了2.5us寬度.再次謝謝!
回復

使用道具 舉報

ID:27513 發表于 2021-11-24 17:53 | 顯示全部樓層
本帖最后由 xxll 于 2021-11-25 07:00 編輯

謝謝各位老師,在這么短的時間內就有許多人參與,出乎我的意料,心情非常激動!大家的建議我一定抽時間一一測試總結經驗.再報告給各位.開先也償試出一個接近答案的程序,但是他不符合中斷的原則.CPU在正程中斷子程序里總總耗費25us.現在也把這個程序給貼出來:
#include <pic.h>
#define uchar unsigned char
#define uint  unsigned int
        uchar TA,TB;
void IO_init(void) /*端口初始化*/
        {

                TRISIO=0x00;
               
        }
void timer2_init(void) //fosc/4   8M所以計數周期為0.5us
        {
                T2CON=0b00000101;        //timer2控制寄存器設置        
                PR2=24;        //25us比較數字
                PEIE=1;        //中斷使能
                TMR2IE=1;                //中斷使能
                GIE=1;       //        開全局中斷
        }
void delay(void)//延時函數
{
         uchar i;
         for(i=2 ;i ; i--);                 
}

/*************************************************/
/*中斷子程序正脈寬為24.6us負脈寬為25.626us,頻率為19.92KHz*/
/*************************************************/
        void interrupt isr(void)
                {
                        GP1=~GP1;//中斷后設引腳反相
                        delay(); //延時
                        TA=GP1;//此項也是為延時2.5us
                        GP0=~TA;//使GP0與GP1反相                        
                        TMR2IF=0;/*TMR2溢出標志清零*/               
                }  
void main(void)
        {
                __CONFIG(FOSC_INTOSCIO&WDTE_OFF);//系統配置,使用內置時鐘,關看門狗
                OSCCONbits.IRCF0=1;
                OSCCONbits.IRCF1=1;
                OSCCONbits.IRCF2=1;//此3條設置時鐘為8M
                IO_init();//端口初始化
                timer2_init();//timer2初始化
                GPIO=0X00;//全部端口設為0
                while(1)  //死循環
                {
               
                        
                }
                        
        }

GAS0004副本.jpg
回復

使用道具 舉報

ID:27513 發表于 2021-11-25 07:25 | 顯示全部樓層
天ノ憶 發表于 2021-11-24 15:25
90后,來一個最簡單的方法,因為手中沒有示波器,只好麻煩樓主驗證一下了,如果還是不行就自動忽略后面的吧 ...

你這種思路很好,但是無法實現!先不說你的初值不對,就中斷定時1US哪個單片機都難實現。本單片機時鐘4M從響應中斷開始壓棧執行子程序到出棧要9到15us。這還要求子程序特別簡單高效才可。
回復

使用道具 舉報

ID:123289 發表于 2021-11-25 07:59 | 顯示全部樓層
增加一個8位的中間 N。初始化時:N=01。 ;目的:對應 GP1=0,GP0=1。
每次中斷后:
GPIO=N
N= N XOR 3   ;目的:對應的 GP1、GP0 求反,準備下次使用。
試試看。
要點:讓GP1、GP0 同時改變。
回復

使用道具 舉報

ID:140489 發表于 2021-11-25 09:29 | 顯示全部樓層
仿真試了下,一路方波正常,兩路波形就亂了
#include <pic.h>

__CONFIG(0x0054);

#define uchar unsigned char
#define uint unsigned int

uchar flag,flag1;

void IO_init(void) /*端口初始化*/
        {
                TRISIO=0x00;
                GP0=0;
                                GP1=0;
        }
void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
        {
                T0CS=0;    //timer0工作于定時器方式
                PSA=1;     //timer0不分頻
                T0IF=0;    //清timer0中斷標志
                TMR0=224; /*置初值 20KHz的半個周期為25us*/
                T0IE=1;    //timer0中斷允許
                GIE=1;     //開全局中斷
        }


void main(void)          //主程序
        {

                IO_init();         //引腳初始化函數
                timer0_init();     //定時器0初始化函數

                while(1)    //死循環
                {
                               if(flag)
                                        {
                                                GP0=1;
        //                                        GP1=!GP0;
                                        }
                                        else
                                        {
                                                GP0=0;
        //                                        GP1=!GP0;                               
                                        }

/*
                        if(flag1)
                                        {
                                                GP1=0;
                               
                                        }
                                        else
                                        {
                                                GP1=1;
                                                                               
                                        }  */                     
                }

        }

void interrupt isr(void)   //中斷子程序
        {

                T0IF=0;    //清中斷標志
                                TMR0=224; //定時器0置初值25us
                 
                                flag = !flag;

        }  

51hei截圖20211125092516.jpg
回復

使用道具 舉報

ID:47286 發表于 2021-11-25 12:29 | 顯示全部樓層
老哥好 PIC一點都不懂 幫不上 我也60后 和您打個招呼
回復

使用道具 舉報

ID:27513 發表于 2021-11-25 13:13 | 顯示全部樓層
lids 發表于 2021-11-25 09:29
仿真試了下,一路方波正常,兩路波形就亂了
#include

謝謝提供方法!剛剛測試了一下,編譯通不過,將配置語句刪除,使用默認的時鐘通過編譯,用示波器看了一下,單腳輸出頻率只有10KHZ且不穩定,占空比似乎是50%但不穩定左右飄忽,怎么調示波都不能很好的同步……
回復

使用道具 舉報

ID:624769 發表于 2021-11-25 17:28 | 顯示全部樓層
xxll 發表于 2021-11-25 13:13
謝謝提供方法!剛剛測試了一下,編譯通不過,將配置語句刪除,使用默認的時鐘通過編譯,用示波器看了一下 ...

PIC12F683 的PDF手冊有么? 發一個上來,我研究一下看看。畢竟有些東西受限于硬件,光看代碼可能忽略掉一些關鍵信息。
回復

使用道具 舉報

ID:27513 發表于 2021-11-25 17:49 | 顯示全部樓層
188610329 發表于 2021-11-25 17:28
PIC12F683 的PDF手冊有么? 發一個上來,我研究一下看看。畢竟有些東西受限于硬件,光看代碼可能忽略掉一 ...

12f683cn.pdf

3.14 MB, 下載次數: 7

回復

使用道具 舉報

ID:27513 發表于 2021-11-25 18:57 | 顯示全部樓層
dzbj 發表于 2021-11-25 12:29
老哥好 PIC一點都不懂 幫不上 我也60后 和您打個招呼

兄弟好!
回復

使用道具 舉報

ID:624769 發表于 2021-11-25 19:29 | 顯示全部樓層
手冊看了一下,發現一個被忽略的問題。
這個片子,只有35條指令,其中對位的操作指令,只有4條,而這個片子速度還比較慢,周期比較長。帶來的直接結果就是:
                      GP1=~GP1;//中斷后設引腳反相
                        GP0=~GP1;//使GP0與GP1反相            
這看似簡單的兩個操作,實際上需要消耗非常多的時間來處理。
通過仔細分析這個片子擁有的35條指令,我認為:
初使狀態  GP0 = 0, GP1 = 1 之后。在翻轉的時候,使用:

GPIO ^= 0x03;  這一條指令來取代  你的:

                        GP1=~GP1;//中斷后設引腳反相
                        GP0=~GP1;//使GP0與GP1反相      

這兩條指令,是比較高效的方法。建議你嘗試一下。

回復

使用道具 舉報

ID:27513 發表于 2021-11-26 08:19 | 顯示全部樓層
188610329 發表于 2021-11-25 19:29
手冊看了一下,發現一個被忽略的問題。
這個片子,只有35條指令,其中對位的操作指令,只有4條,而這個片 ...

按照你的方法試了一下,沒有波形輸出只有直流電壓。
其實這個真正的原因,我個人認為不是操作快慢的問題,而是CPU離開中斷子程序輸出引腳信號立即再次翻轉的問題。像前面我示出的一個例子,在子程序里延時即可得到想要的波形。
這個程序原意是:1。CPU給引腳付值然后延時,CPU跳出再干別的事。等延時到CPU在回去給相關引腳重新付值,就這樣周而復始下去的。現在的問題就是在正程時間的延時都給了逆程時間了。
如將子程序中指令位置上下調換,只影響逆程時長,不影響正程脈寬
TMR0=224;
T0IF=0;
GP1=!GP1;
GP0=!GP1;
這樣的正脈沖是4.8US,負脈寬是50.2US,頻率為19.9KHz;
GP1=!GP1;
GP0=!GP1;
TMR0=224;
T0IF=0;
這樣調換一下順序,正程脈寬仍然是4.8us,但負脈寬變成了54.4us,頻率降到16.8KHz;
TMR0=224;
T0IF=0;
GP1=!GP1;
TA=!GP1;
GP0=TA;
在這段里加入一個變量TA,正脈寬會變成5.48us,負脈寬縮小,頻率不變仍是19.Khz;
你看從這里能不能想出解決方案來!
回復

使用道具 舉報

ID:548551 發表于 2021-11-26 09:20 | 顯示全部樓層
我現在用得單片機剛好是PIC架構得。我看了半天不知道理解對不對。你想GP1輸出的正占空比,GP0輸出的正占空比是GP0的負占空比時間,假如1現在的正占空比是10%,那么GP0輸出的正占空比就應該是90%對吧。您是這意思么?
回復

使用道具 舉報

ID:342822 發表于 2021-11-26 09:38 | 顯示全部樓層
lids 發表于 2021-11-25 09:29
仿真試了下,一路方波正常,兩路波形就亂了
#include

一路方波正常很好~~加個7404反相器就成了互補波形了
回復

使用道具 舉報

ID:27513 發表于 2021-11-26 09:41 | 顯示全部樓層
xqleft 發表于 2021-11-26 09:20
我現在用得單片機剛好是PIC架構得。我看了半天不知道理解對不對。你想GP1輸出的正占空比,GP0輸出的正占空 ...

我要的就是一個引腳上正50%,負50%就這樣簡單,要求是用定時器0實現,頻率20KHZ
回復

使用道具 舉報

ID:401564 發表于 2021-11-26 14:36 | 顯示全部樓層
還在折騰這個?
TMR0=0xE0(224),定時器就是256-224=32
如果你是用4MHZ時鐘,那么,定時器的中斷時間是不低于32uS的,你這還怎么達到?20KHZ的輸出?
TMR0=0xE0; /*置初值 20KHz的半個周期為25us*/..........這是怎么算出來的?
而且,PIC是沒有堆棧指令的,編譯器可能還要加幾條保存W和其它會改變的文件寄存器的指令
這樣一來,你這個是肯定不會有20KHZ的頻率的
而且,在中斷程序中,盡量少用變量計算,沒有用過PIC的C,不知道PIC有沒有位,如果有位,就用位來判斷,定時器設定要高于20KHZ,TMR0的值要大于0xe7
先聲明一個位
void interrupt isr(void)   //中斷子程序
                {
                        TMR0=240; //定時器0置初值,先看結果,再慢慢調節
                        T0IF=0;    //清中斷標志
                        if(ON)
                             {
                               GP0=1;
                                GP1=0;
                               ON=0;
                             }   
                       else
                             {
                               GP0=0;
                                GP1=1;
                               ON=1;
                             }                                
                }

回復

使用道具 舉報

ID:27513 發表于 2021-11-26 18:19 | 顯示全部樓層
Y_G_G 發表于 2021-11-26 14:36
還在折騰這個?
TMR0=0xE0(224),定時器就是256-224=32
如果你是用4MHZ時鐘,那么,定時器的中斷時間是不低于 ...

這位老師好!我把你的方案和數據測試結果匯報給你:時鐘4M時,GP0正脈寬0.8us負脈寬75.2us頻率13KHz;
GP1正脈寬38.8us,負脈寬37.6us,頻率13KHZ

時鐘設置成8M時:GP0正脈寬0.5us(500ns),負脈寬示波器沒報,頻率26.3KHZ;
GP1正脈寬19.4us,負脈寬18.6us,頻率26.3KHz
老師從這二種時鐘數據看,只有GP1正負脈沖占空比能接近50%,而GP0正脈沖太窄,你看如何解決?
回復

使用道具 舉報

ID:401564 發表于 2021-11-26 18:54 | 顯示全部樓層
xxll 發表于 2021-11-26 18:19
這位老師好!我把你的方案和數據測試結果匯報給你:時鐘4M時,GP0正脈寬0.8us負脈寬75.2us頻率13KHz;
GP1 ...

你把完整的代碼上傳一下
GP0和GP1是一樣的調整,在時間上應該是一致的,沒有理由只有一個行,一個不行的,要么就都不行,要么就都行
你也可以自己調試一下的呀,把GP1代碼刪除,或者把GP0換成其它的端口試一下
void interrupt isr(void)   //中斷子程序
                {
                        
                        T0IF=0;    //清中斷標志
                        if(ON)
                             {
                               GP0=1;
                                GP1=0;
                               ON=0;
                             }   
                       else
                             {
                               GP0=0;
                                GP1=1;
                               ON=1;
                             }   
TMR0=240; //定時器0置初值,先看結果,這設置放后面                           
                }
回復

使用道具 舉報

ID:27513 發表于 2021-11-26 20:44 | 顯示全部樓層
18434225 發表于 2021-11-26 18:45
從你這個圖可以看出,那個脈沖是你每次進去之后GP0=~GP0取反的結果,后面變低是因為你又GP1=!GP0,使其變低 ...

正半周25us+負半周25us,總周期是50us哪來的40KHZ,這個單片機20KHZ都可能做不督到,還40K
雙腳輸出互補的方波如果拿來驅動逆變半橋,GP1=GP0想想是什么后果?再都為了試驗,前面說過都試過了,沒有變化,是一樣的。這東西折騰很久了,不是我執著,論個所以然,早就放棄了……
回復

使用道具 舉報

ID:624769 發表于 2021-11-26 21:34 | 顯示全部樓層
老哥, 你說…… ,會不會是因為:

ANSEL = 0; 這句沒寫的關系。

我琢磨了很久,你在頂樓說的,刪除了GP1 = !GP0;  就沒輸出了, 你覺得不應該,我也覺得不應該,所以,我在想,是不是一開始咱們就沒找對方向? 其實就是端口的初始化沒有做好? 所以沒有輸出?
回復

使用道具 舉報

ID:27513 發表于 2021-11-27 09:08 | 顯示全部樓層
188610329 發表于 2021-11-26 21:34
老哥, 你說…… ,會不會是因為:

ANSEL = 0; 這句沒寫的關系?

ANSEL寄存器是為模擬信號輸入設置寄存器和它沒關系,端口就這兩個寄存器TRISIO和GPIO
回復

使用道具 舉報

ID:27513 發表于 2021-11-27 09:23 | 顯示全部樓層
xxll 發表于 2021-11-26 20:44
正半周25us+負半周25us,總周期是50us哪來的40KHZ,這個單片機20KHZ都可能做不督到,還40K
雙腳輸出互補 ...

#include <pic.h>
#define uchar unsigned char
uchar ON;
void IO_init(void) /*端口初始化*/
        {
                TRISIO=0x00;
                GPIO=0X00;
        }
void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
        {
                T0CS=0;    //timer0工作于定時器方式
                PSA=1;     //timer0不分頻
                T0IF=0;    //清timer0中斷標志
                TMR0=224; /*置初值 20KHz的半個周期為25us*/
                T0IE=1;    //timer0中斷允許
                GIE=1;     //開全局中斷
        }

        void interrupt isr(void)   //中斷子程序
                {
                        TMR0=224; //定時器0置初值25us               
                        T0IF=0;    //清中斷標志                                       
                if(ON)
                        {
        //                TMR0=224; //定時器0置初值25us               
        //                T0IF=0;    //清中斷標志                       
                        GP2=0;
                        GP1=1;
                        ON=0;
                        }
                else
                        {
                //        TMR0=224; //定時器0置初值25us               
                //        T0IF=0;    //清中斷標志
                        GP1=0;
                        GP2=1;
                        ON=1;                       
                        }
       
                //        GP0=~GP0;  //GP0位取反
                //        GP1=!GP0;  //使GP1引腳取反GP0               
               
                        /*在這里廢寢忘食3總天,一度引起孫子的奶奶發飆
                                也沒有折騰出正確的結果*/                                
                }  
void main(void)          //主程序
        {
                OSCCONbits.IRCF0=1;
                OSCCONbits.IRCF1=1;
                OSCCONbits.IRCF2=1;//此3條設置時鐘為8M
                IO_init();         //引腳初始化函數
                timer0_init();     //定時器0初始化函數
                GP1=1;
                GP2=0;
                while(1)    //死循環
                {
               
                       
                }
                       
        }
花括號里的順序誰在前誰就是窄脈沖,和TMR0、T0IF所在位置無關,但和頻率高低有較大的關系。稍后我將發個統計表格上來供大家研究!

GAS0002副本.jpg
GAS0004副本.jpg
回復

使用道具 舉報

ID:401564 發表于 2021-11-27 12:00 | 顯示全部樓層
xxll 發表于 2021-11-27 09:08
ANSEL寄存器是為模擬信號輸入設置寄存器和它沒關系,端口就這兩個寄存器TRISIO和GPIO

你試過增加ANSEL=0x00;這語句沒有?
ANSEL 是要先清除的!
回復

使用道具 舉報

ID:401564 發表于 2021-11-27 12:25 | 顯示全部樓層
xxll 發表于 2021-11-27 09:08
ANSEL寄存器是為模擬信號輸入設置寄存器和它沒關系,端口就這兩個寄存器TRISIO和GPIO

還要添加一條:
CMCON0=0x07;
回復

使用道具 舉報

ID:27513 發表于 2021-11-27 19:56 | 顯示全部樓層
Y_G_G 發表于 2021-11-26 14:36
還在折騰這個?
TMR0=0xE0(224),定時器就是256-224=32
如果你是用4MHZ時鐘,那么,定時器的中斷時間是不低于 ...

關于這里的TMRO=224是因為時鐘是8M時設的值,(256-224)*0.5=16us在8M時鐘時CPU執行中斷大約耗費9us (后面也證實了),16+9=25
回復

使用道具 舉報

ID:624769 發表于 2021-11-27 20:17 | 顯示全部樓層
xxll 發表于 2021-11-27 09:08
ANSEL寄存器是為模擬信號輸入設置寄存器和它沒關系,端口就這兩個寄存器TRISIO和GPIO

從你發的手冊上看,

ANSEL 控制引腳是模擬輸入,還是數字輸出。
如果 有 位置1則為模擬輸入,如果該位置0則為數字輸出。
手冊上看,上電后 ANSEL 的初值不為0。
并且,手冊上還說,上電后端口初始化 ANSEL 需要 置 0 復位。
另外,和GPIO有關的寄存器,總共有11個,
GPIO.png
此表中,沒有打陰影的部分,都是會影響GPIO的輸出的設置。
通過此表也能看到,ANSEL 不設置0的話,GPIO0~GPIO3 默認為模擬輸入。
回復

使用道具 舉報

ID:342822 發表于 2021-11-27 22:34 | 顯示全部樓層
雖然占空比沒達到百分之50,但已經是互補方波了 屏幕截圖(76).png



/* Main.c file generated by New Project wizard
*
* Created:   周六 11月 27 2021
* Processor: PIC12F683
* Compiler:  HI-TECH C for PIC10/12/16
*/

#include <pic.h>

__CONFIG(0x0054);

#define uchar unsigned char
#define uint unsigned int

uchar flag,flag1;

void IO_init(void) /*端口初始化*/
        {
                TRISIO=0x00;
                GPIO==0b00000000;

        }
void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
        {
                T0CS=0;    //timer0工作于定時器方式
                PSA=1;     //timer0不分頻
                T0IF=0;    //清timer0中斷標志
                TMR0=224; /*置初值 20KHz的半個周期為25us*/
                T0IE=1;    //timer0中斷允許
                GIE=1;     //開全局中斷
        }


void main(void)          //主程序
        {

                IO_init();         //引腳初始化函數
                timer0_init();     //定時器0初始化函數

                while(1)    //死循環
                {
                               if(flag)
                                        {
                                                GPIO=0B00000001;

                                        }
                                        else
                                        {
                                                 GPIO=0B00000010;

                                        }



                }

        }

void interrupt isr(void)   //中斷子程序
        {

                T0IF=0;    //清中斷標志
                                TMR0=224; //定時器0置初值25us

                                flag = !flag;

        }  

回復

使用道具 舉報

ID:342822 發表于 2021-11-28 00:10 | 顯示全部樓層
本帖最后由 taotie 于 2021-11-29 14:49 編輯

屏幕截圖(111).png

相差無幾
時鐘8Mhz,標志判斷的內容由死循環轉到中斷子程序中。
初值設置為225     方波頻率=20000hz


* Created:   周六 11月 27 2021
* Processor: PIC12F683
* Compiler:  HI-TECH C for PIC10/12/16
*/

#include <pic.h>

__CONFIG(0x0054);

#define uchar unsigned char
#define uint unsigned int

uchar flag,flag1;

void IO_init(void) /*端口初始化*/
        {
                TRISIO=0x00;
                GPIO==0b00000000;

        }
void timer0_init(void) //定時器0初始化使用系統默認時鐘4M fosc/4 所以計數周期為1us
        {
                T0CS=0;    //timer0工作于定時器方式
                PSA=1;     //timer0不分頻
                T0IF=0;    //清timer0中斷標志
                TMR0=225; /*置初值 20KHz的半個周期為25us*/
                T0IE=1;    //timer0中斷允許
                GIE=1;     //開全局中斷
        }


void main(void)          //主程序
        {

                IO_init();         //引腳初始化函數
                timer0_init();     //定時器0初始化函數

                while(1)    //死循環
         {      

}
        }

void interrupt isr(void)   //中斷子程序
        {

               //T0IF=0;    //清中斷標志
                TMR0=225; //定時器0置初值25us
{
                if(flag)
         {
                      GPIO=0B00000001;

                }
                         else
                     {
                         GPIO=0B00000010;

                      }

                        T0IF=0;

                }

                             flag = !flag;                       

        }  

回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产在线观看 | 毛片高清| 久久精品亚洲精品国产欧美kt∨ | 在线看中文字幕 | 国产在线激情视频 | 日本一级淫片免费啪啪3 | va精品| 日韩成人在线视频 | 久久久久网站 | 天天操天天摸天天爽 | 97视频成人 | 成人免费一区二区三区视频网站 | 精久久久久| 国产精品a一区二区三区网址 | 日韩精品一区二区三区视频播放 | 中文字幕高清免费日韩视频在线 | 久久久久一区二区三区 | 亚洲在线久久 | 久草免费在线视频 | 亚洲欧美中文日韩在线v日本 | 91av导航 | 色视频www在线播放国产人成 | 成人精品一区 | 日本中文在线视频 | 欧美一级片在线看 | 午夜欧美一区二区三区在线播放 | 国产精品成人品 | 99亚洲精品 | 亚洲码欧美码一区二区三区 | 亚洲男人的天堂网站 | 中文字幕在线免费视频 | 精品视频99 | 国产精品久久久久久久粉嫩 | 精品一区二区久久 | 日韩av一区在线观看 | 日本一区二区三区四区 | 日韩久久久久久 | 国产免费色 | 亚洲精品国产精品国自产在线 | 国产成人久久av免费高清密臂 | 日韩成人av在线 |