標(biāo)題: PIC單片機(jī)輸出不了占空比50%的方波——幫扶一把學(xué)單片機(jī)的60后 [打印本頁]
作者: xxll 時間: 2021-11-24 11:18
標(biāo)題: PIC單片機(jī)輸出不了占空比50%的方波——幫扶一把學(xué)單片機(jī)的60后
自我介紹下:60后從業(yè)模電,自封工程師,動手能力強(qiáng)。學(xué)單片機(jī)歷程30年,學(xué)級仍是未入門的學(xué)前班。所以各位看官都是我的老師,各位的每句話都能使我進(jìn)步!期望大家都出一份正能量!廢話不說入正題:
PIC12F683單片機(jī),編程平臺MPLAB IDE -V8.84 編譯器HI-TECH-PICC_9.83
無單片機(jī)開發(fā)板,有RF809H編程器,有GA1202CAL示波器
實(shí)驗(yàn)要求單片機(jī)GP0和GP1輸出20KHz占空比為50%的互補(bǔ)方波
C程序:
#include <pic.h>
void IO_init(void) /*端口初始化*/
{
TRISIO=0x00;
GPIO=0X00;
}
void timer0_init(void) //定時器0初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標(biāo)志
TMR0=0xE0; /*置初值 20KHz的半個周期為25us*/
T0IE=1; //timer0中斷允許
GIE=1; //開全局中斷
}
void interrupt isr(void) //中斷子程序
{
TMR0=0xE0; //定時器0置初值25us
T0IF=0; //清中斷標(biāo)志
GP0=~GP0; //GP0位取反
GP1=!GP0; //使GP1引腳取反GP0
/*在這里廢寢忘食3總天,一度引起孫子的奶奶發(fā)飆
也沒有折騰出正確的結(jié)果*/
}
void main(void) //主程序
{
IO_init(); //引腳初始化函數(shù)
timer0_init(); //定時器0初始化函數(shù)
while(1) //死循環(huán)
{
}
}
寫入單片機(jī);手工搭建最小系統(tǒng)上示波器看波形結(jié)果頻率是26.3KHz,GP0引腳正占空比只有12.6%,負(fù)占空比87.3%;GP1引腳正占空比86.3%,負(fù)占空比13.6%幅值5.04V
刪除中斷子程序里的GP1=!GP0語句結(jié)果GP0引腳示波器上只有一條5.17V的直線沒有波形了,頻率顯示為小于10Hz.
大家說怪不怪!本應(yīng)該GP0輸出信號不受影響的怎么就沒有了呢????
接下來就是折騰了反復(fù)換TMR0的初值,最后試到0xE0時頻率是19.96KHz正占空比9.6%負(fù)占空比是90.4%,也就是說正脈沖的寬度是4.8us這個值基本是恒定的試了下,從10KHz到30KHz這個值不變.然后大發(fā)現(xiàn)這個4.8us竟然是執(zhí)行GP1=!GP0 這條語句所耗費(fèi)的時間,所以上述刪除這條語句示波器上只顯示一直線。
-
GAS0002副本.jpg
(105.12 KB, 下載次數(shù): 114)
下載附件
2021-11-24 11:18 上傳
作者: xxll 時間: 2021-11-24 11:31
本帖最后由 xxll 于 2021-11-24 12:03 編輯
現(xiàn)在的問題就是怎樣才能使正負(fù)波形占空比為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所以計數(shù)周期為0.5us
{
T2CON=0b00000101; //timer2控制寄存器設(shè)置
PR2=24; //25us比較數(shù)字
PEIE=1; //模塊中斷使能
TMR2IE=1; //定時器2中斷使能
GIE=1; // 開全局中斷
}
void interrupt isr(void)
{
GP1=~GP1;//中斷后設(shè)引腳反相
GP0=~GP1;//使GP0與GP1反相
TMR2IF=0;/*TMR2溢出標(biāo)志清零*/
}
void main(void)
{
__CONFIG(FOSC_INTOSCIO&WDTE_OFF);//系統(tǒng)配置,使用內(nèi)置時鐘,關(guān)看門狗
OSCCONbits.IRCF0=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;//此3條設(shè)置時鐘為8M
IO_init();//端口初始化
timer2_init();//timer2初始化
GPIO=0X00;//全部端口設(shè)為0
while(1) //死循環(huán)
{
}
}
-
GAS0003副本.jpg
(105.41 KB, 下載次數(shù): 107)
下載附件
2021-11-24 12:03 上傳
作者: 188610329 時間: 2021-11-24 13:42
PIC 沒玩過,本不該發(fā)言,但是看你帖子實(shí)在冷清,深感年紀(jì)大了學(xué)單片機(jī)之不易……,
作為70后,在你身上看到10年后的自己,所以多多少少想幫你頂一把。
雖然PIC沒有玩過, 有些道理應(yīng)該是互通的所以說兩句。
GP0=~GP0; //GP0位取反
GP1=!GP0; //使GP1引腳取反GP0
基于單片機(jī)的工作原理,這里很可能得不到你希望的結(jié)果…… 舉個簡單的例子。
GP0 = ~GP0; 這里的等號左邊 和 等號右邊,其實(shí)是不同的東西。
等號的右邊,是當(dāng)前GP0的電平狀態(tài),綜合了外部電平和內(nèi)部設(shè)置之后的最后結(jié)果,然后通過~取反
等號左邊,是你給GP0 設(shè)置的新狀態(tài)即會改變GP0的內(nèi)部電平關(guān)系,然后通過這個內(nèi)部關(guān)系再去改變端口的外部關(guān)系。
當(dāng)你運(yùn)行完 GP0 = ~GP0 立刻運(yùn)行 GP1=!GP0; 此時讀取的 GP0, 如上所說是結(jié)合內(nèi)部設(shè)置和外部電平綜合后的一個狀態(tài),而不是你剛剛賦值的結(jié)果,由于各種單片機(jī)不同我不能說100%,但是有很大的概率,這個時候的GP0,是并沒有完成 GP0 = ~GP0 這個操作后更新 的狀態(tài)。 但,也有可能已經(jīng)完成了更新。這個不好判斷,所以在時序允許的情況下,一般應(yīng)該這么寫代碼。
GP1= GP0; //使GP1引腳取GP0
GP0= !GP0; //GP0位取反
這樣能保障,兩次讀到的GP0 是相等的。
如果,你一定要先改GP0, 再改GP1 那么也可以用一個中間變量
F0 = GP0;
GP0 = !F0;
GP1 = F0;
這樣是比較安全的操作。
作者: AUG 時間: 2021-11-24 13:55
本帖最后由 AUG 于 2021-11-24 14:01 編輯
從你這個圖可以看出,那個脈沖是你每次進(jìn)去之后GP0=~GP0取反的結(jié)果,后面變低是因?yàn)槟阌諫P1=!GP0,使其變低了.建議如下操作
void main()
{
timer_init();//25us一次中斷 40KHz
GP0 = 1; //起始值相反
GP1 = 0;
while(1);
}
interrupt timer(void)
{
//重裝計數(shù)值
//清中斷
GP1=GP0;
GP0=~GP0;
}
作者: qiangtech 時間: 2021-11-24 14:18
用過一個仿PIC的芯片。
用的T0做的510US定時:
1.jpg (13.6 KB, 下載次數(shù): 46)
下載附件
2021-11-24 14:16 上傳
用的T1做的38KHz的方波:
2.jpg (12.08 KB, 下載次數(shù): 39)
下載附件
2021-11-24 14:16 上傳
中斷里的IO翻轉(zhuǎn)。
3.jpg (5.49 KB, 下載次數(shù): 42)
下載附件
2021-11-24 14:16 上傳
作者: qiangtech 時間: 2021-11-24 14:19
不確定寄存器完全一致的,你可以參考一下,看著修改。
作者: Y_G_G 時間: 2021-11-24 14:26
中斷程序這樣改試一下:
void interrupt isr(void) //中斷子程序
{
TMR0=0xE0; //定時器0置初值25us
T0IF=0; //清中斷標(biāo)志
GP1=GP0; //使GP1引腳取反GP0后的GP0
GP0=~GP0; //GP0位取反
}
其它參考意見:
PIC我用過,個人感覺PIC實(shí)在不適合單片機(jī)入門,更多的是工業(yè)產(chǎn)品才用的,很多操作是有嚴(yán)格要求的,比如硬件堆棧,甚至很多學(xué)單片機(jī)的對堆棧也只是百度大概的看一遍,但真正到PIC硬件堆棧的時候,問題就出來了
IO的數(shù)據(jù)方向要注意,中斷只有一個入口.......
數(shù)據(jù)手冊是肯定要一邊寫代碼一邊看的,但PIC的8位單片機(jī)數(shù)據(jù)手冊都是匯編的,印象中是沒有C的,所以,匯編指令最好是也要會一點(diǎn),不要求能寫程序,至少對著指令能看明白
作者: hz_dyg 時間: 2021-11-24 15:11
一般來說,端口設(shè)置和讀取的寄存器是分開的,設(shè)置后馬上讀取,單片機(jī)速度太快,讀取狀態(tài)值不一定是穩(wěn)定后的值。最好定義個變量 bit status, 中斷里改變status = !status; 然后賦值給端口寄存器
作者: yzwzfyz 時間: 2021-11-24 15:12
增加一個中間變T.
每次中斷后:
GP0=T
T=!T
GP1=T
試試看。
作者: yzwzfyz 時間: 2021-11-24 15:13
如果成功,再告訴你原因。不成功就罷了。
作者: 天ノ憶 時間: 2021-11-24 15:25
90后,來一個最簡單的方法,因?yàn)槭种袥]有示波器,只好麻煩樓主驗(yàn)證一下了,如果還是不行就自動忽略后面的吧,一般來說對定時器要求較高,定時器中斷里處理的代碼越少越好,能少就盡量少,以下是代碼- #include <pic.h>
- char i = 0;
- void IO_init(void) /*端口初始化*/
- {
- TRISIO=0x00;
- GPIO=0X00;
- }
- void timer0_init(void) //定時器0初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
- {
- T0CS=0; //timer0工作于定時器方式
- PSA=1; //timer0不分頻
- T0IF=0; //清timer0中斷標(biāo)志
- TMR0=0x01; /*置初值 20KHz的半個周期為25us*/
- T0IE=1; //timer0中斷允許
- GIE=1; //開全局中斷
- }
- void main()
- {
- IO_init(); //引腳初始化函數(shù)
- timer0_init(); //定時器0初始化函數(shù)
- while()
- {
- if(i >= 50) {
- i = 1;
- }else if(i >= 25) {
- GP0 = 1;
- GP1 = 0;
- }else if(i >= 0) {
- GP0 = 0;
- GP1 = 1;
- }
- }
- }
- void interrupt isr(void) //中斷子程序
- {
- TMR0 = 0x01; //定時器0置初值1us
- T0IF = 0; //清中斷標(biāo)志
- i ++;
- }
復(fù)制代碼
作者: xxll 時間: 2021-11-24 16:38
首先謝謝你,你這種方法我之前也試過,正脈沖的寬度只增加2.5us
作者: xxll 時間: 2021-11-24 17:26
感謝您的參與,你說的第一種GP0=~GP0;GP1=!GP0;剛試過結(jié)果脈寬沒有改變.這種順序改變在示波器上觀看沒有變化的.當(dāng)然,我知道編程是要講究時序的,否則實(shí)際應(yīng)用中會出大問題的!至于第二種方法我在早些時候也試過,中間加一個變量操作,確實(shí)增加了2.5us寬度.再次謝謝!
作者: xxll 時間: 2021-11-24 17:53
本帖最后由 xxll 于 2021-11-25 07:00 編輯
謝謝各位老師,在這么短的時間內(nèi)就有許多人參與,出乎我的意料,心情非常激動!大家的建議我一定抽時間一一測試總結(jié)經(jīng)驗(yàn).再報告給各位.開先也償試出一個接近答案的程序,但是他不符合中斷的原則.CPU在正程中斷子程序里總總耗費(fèi)25us.現(xiàn)在也把這個程序給貼出來:
#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所以計數(shù)周期為0.5us
{
T2CON=0b00000101; //timer2控制寄存器設(shè)置
PR2=24; //25us比較數(shù)字
PEIE=1; //中斷使能
TMR2IE=1; //中斷使能
GIE=1; // 開全局中斷
}
void delay(void)//延時函數(shù)
{
uchar i;
for(i=2 ;i ; i--);
}
/*************************************************/
/*中斷子程序正脈寬為24.6us負(fù)脈寬為25.626us,頻率為19.92KHz*/
/*************************************************/
void interrupt isr(void)
{
GP1=~GP1;//中斷后設(shè)引腳反相
delay(); //延時
TA=GP1;//此項(xiàng)也是為延時2.5us
GP0=~TA;//使GP0與GP1反相
TMR2IF=0;/*TMR2溢出標(biāo)志清零*/
}
void main(void)
{
__CONFIG(FOSC_INTOSCIO&WDTE_OFF);//系統(tǒng)配置,使用內(nèi)置時鐘,關(guān)看門狗
OSCCONbits.IRCF0=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;//此3條設(shè)置時鐘為8M
IO_init();//端口初始化
timer2_init();//timer2初始化
GPIO=0X00;//全部端口設(shè)為0
while(1) //死循環(huán)
{
}
}
-
GAS0004副本.jpg
(103.03 KB, 下載次數(shù): 107)
下載附件
2021-11-25 07:00 上傳
作者: xxll 時間: 2021-11-25 07:25
你這種思路很好,但是無法實(shí)現(xiàn)!先不說你的初值不對,就中斷定時1US哪個單片機(jī)都難實(shí)現(xiàn)。本單片機(jī)時鐘4M從響應(yīng)中斷開始壓棧執(zhí)行子程序到出棧要9到15us。這還要求子程序特別簡單高效才可。
作者: yzwzfyz 時間: 2021-11-25 07:59
增加一個8位的中間 N。初始化時:N=01。 ;目的:對應(yīng) GP1=0,GP0=1。
每次中斷后:
GPIO=N
N= N XOR 3 ;目的:對應(yīng)的 GP1、GP0 求反,準(zhǔn)備下次使用。
試試看。
要點(diǎn):讓GP1、GP0 同時改變。
作者: lids 時間: 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初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標(biāo)志
TMR0=224; /*置初值 20KHz的半個周期為25us*/
T0IE=1; //timer0中斷允許
GIE=1; //開全局中斷
}
void main(void) //主程序
{
IO_init(); //引腳初始化函數(shù)
timer0_init(); //定時器0初始化函數(shù)
while(1) //死循環(huán)
{
if(flag)
{
GP0=1;
// GP1=!GP0;
}
else
{
GP0=0;
// GP1=!GP0;
}
/*
if(flag1)
{
GP1=0;
}
else
{
GP1=1;
} */
}
}
void interrupt isr(void) //中斷子程序
{
T0IF=0; //清中斷標(biāo)志
TMR0=224; //定時器0置初值25us
flag = !flag;
}
-
51hei截圖20211125092516.jpg
(93.61 KB, 下載次數(shù): 106)
下載附件
2021-11-25 09:29 上傳
作者: dzbj 時間: 2021-11-25 12:29
老哥好 PIC一點(diǎn)都不懂 幫不上 我也60后 和您打個招呼
作者: xxll 時間: 2021-11-25 13:13
謝謝提供方法!剛剛測試了一下,編譯通不過,將配置語句刪除,使用默認(rèn)的時鐘通過編譯,用示波器看了一下,單腳輸出頻率只有10KHZ且不穩(wěn)定,占空比似乎是50%但不穩(wěn)定左右飄忽,怎么調(diào)示波都不能很好的同步……
作者: 188610329 時間: 2021-11-25 17:28
PIC12F683 的PDF手冊有么? 發(fā)一個上來,我研究一下看看。畢竟有些東西受限于硬件,光看代碼可能忽略掉一些關(guān)鍵信息。
作者: xxll 時間: 2021-11-25 17:49
-
-
12f683cn.pdf
2021-11-25 18:34 上傳
點(diǎn)擊文件名下載附件
3.14 MB, 下載次數(shù): 7
作者: xxll 時間: 2021-11-25 18:57
兄弟好!
作者: 188610329 時間: 2021-11-25 19:29
手冊看了一下,發(fā)現(xiàn)一個被忽略的問題。
這個片子,只有35條指令,其中對位的操作指令,只有4條,而這個片子速度還比較慢,周期比較長。帶來的直接結(jié)果就是:
GP1=~GP1;//中斷后設(shè)引腳反相
GP0=~GP1;//使GP0與GP1反相
這看似簡單的兩個操作,實(shí)際上需要消耗非常多的時間來處理。
通過仔細(xì)分析這個片子擁有的35條指令,我認(rèn)為:
初使?fàn)顟B(tài) GP0 = 0, GP1 = 1 之后。在翻轉(zhuǎn)的時候,使用:
GPIO ^= 0x03; 這一條指令來取代 你的:
GP1=~GP1;//中斷后設(shè)引腳反相
GP0=~GP1;//使GP0與GP1反相
這兩條指令,是比較高效的方法。建議你嘗試一下。
作者: xxll 時間: 2021-11-26 08:19
按照你的方法試了一下,沒有波形輸出只有直流電壓。
其實(shí)這個真正的原因,我個人認(rèn)為不是操作快慢的問題,而是CPU離開中斷子程序輸出引腳信號立即再次翻轉(zhuǎn)的問題。像前面我示出的一個例子,在子程序里延時即可得到想要的波形。
這個程序原意是:1。CPU給引腳付值然后延時,CPU跳出再干別的事。等延時到CPU在回去給相關(guān)引腳重新付值,就這樣周而復(fù)始下去的。現(xiàn)在的問題就是在正程時間的延時都給了逆程時間了。
如將子程序中指令位置上下調(diào)換,只影響逆程時長,不影響正程脈寬
TMR0=224;
T0IF=0;
GP1=!GP1;
GP0=!GP1;
這樣的正脈沖是4.8US,負(fù)脈寬是50.2US,頻率為19.9KHz;
GP1=!GP1;
GP0=!GP1;
TMR0=224;
T0IF=0;
這樣調(diào)換一下順序,正程脈寬仍然是4.8us,但負(fù)脈寬變成了54.4us,頻率降到16.8KHz;
TMR0=224;
T0IF=0;
GP1=!GP1;
TA=!GP1;
GP0=TA;
在這段里加入一個變量TA,正脈寬會變成5.48us,負(fù)脈寬縮小,頻率不變?nèi)允?9.Khz;
你看從這里能不能想出解決方案來!
作者: xqleft 時間: 2021-11-26 09:20
我現(xiàn)在用得單片機(jī)剛好是PIC架構(gòu)得。我看了半天不知道理解對不對。你想GP1輸出的正占空比,GP0輸出的正占空比是GP0的負(fù)占空比時間,假如1現(xiàn)在的正占空比是10%,那么GP0輸出的正占空比就應(yīng)該是90%對吧。您是這意思么?
作者: taotie 時間: 2021-11-26 09:38
一路方波正常很好~~加個7404反相器就成了互補(bǔ)波形了
作者: xxll 時間: 2021-11-26 09:41
我要的就是一個引腳上正50%,負(fù)50%就這樣簡單,要求是用定時器0實(shí)現(xiàn),頻率20KHZ
作者: Y_G_G 時間: 2021-11-26 14:36
還在折騰這個?
TMR0=0xE0(224),定時器就是256-224=32
如果你是用4MHZ時鐘,那么,定時器的中斷時間是不低于32uS的,你這還怎么達(dá)到?20KHZ的輸出?
TMR0=0xE0; /*置初值 20KHz的半個周期為25us*/..........這是怎么算出來的?
而且,PIC是沒有堆棧指令的,編譯器可能還要加幾條保存W和其它會改變的文件寄存器的指令
這樣一來,你這個是肯定不會有20KHZ的頻率的
而且,在中斷程序中,盡量少用變量計算,沒有用過PIC的C,不知道PIC有沒有位,如果有位,就用位來判斷,定時器設(shè)定要高于20KHZ,TMR0的值要大于0xe7
先聲明一個位
void interrupt isr(void) //中斷子程序
{
TMR0=240; //定時器0置初值,先看結(jié)果,再慢慢調(diào)節(jié)
T0IF=0; //清中斷標(biāo)志
if(ON)
{
GP0=1;
GP1=0;
ON=0;
}
else
{
GP0=0;
GP1=1;
ON=1;
}
}
作者: xxll 時間: 2021-11-26 18:19
這位老師好!我把你的方案和數(shù)據(jù)測試結(jié)果匯報給你:時鐘4M時,GP0正脈寬0.8us負(fù)脈寬75.2us頻率13KHz;
GP1正脈寬38.8us,負(fù)脈寬37.6us,頻率13KHZ
時鐘設(shè)置成8M時:GP0正脈寬0.5us(500ns),負(fù)脈寬示波器沒報,頻率26.3KHZ;
GP1正脈寬19.4us,負(fù)脈寬18.6us,頻率26.3KHz
老師從這二種時鐘數(shù)據(jù)看,只有GP1正負(fù)脈沖占空比能接近50%,而GP0正脈沖太窄,你看如何解決?
作者: Y_G_G 時間: 2021-11-26 18:54
你把完整的代碼上傳一下
GP0和GP1是一樣的調(diào)整,在時間上應(yīng)該是一致的,沒有理由只有一個行,一個不行的,要么就都不行,要么就都行
你也可以自己調(diào)試一下的呀,把GP1代碼刪除,或者把GP0換成其它的端口試一下
void interrupt isr(void) //中斷子程序
{
T0IF=0; //清中斷標(biāo)志
if(ON)
{
GP0=1;
GP1=0;
ON=0;
}
else
{
GP0=0;
GP1=1;
ON=1;
}
TMR0=240; //定時器0置初值,先看結(jié)果,這設(shè)置放后面
}
作者: xxll 時間: 2021-11-26 20:44
正半周25us+負(fù)半周25us,總周期是50us哪來的40KHZ,這個單片機(jī)20KHZ都可能做不督到,還40K
雙腳輸出互補(bǔ)的方波如果拿來驅(qū)動逆變半橋,GP1=GP0想想是什么后果?再都為了試驗(yàn),前面說過都試過了,沒有變化,是一樣的。這東西折騰很久了,不是我執(zhí)著,論個所以然,早就放棄了……
作者: 188610329 時間: 2021-11-26 21:34
老哥, 你說…… ,會不會是因?yàn)椋?br />
ANSEL = 0; 這句沒寫的關(guān)系?
我琢磨了很久,你在頂樓說的,刪除了GP1 = !GP0; 就沒輸出了, 你覺得不應(yīng)該,我也覺得不應(yīng)該,所以,我在想,是不是一開始咱們就沒找對方向? 其實(shí)就是端口的初始化沒有做好? 所以沒有輸出?
作者: xxll 時間: 2021-11-27 09:08
ANSEL寄存器是為模擬信號輸入設(shè)置寄存器和它沒關(guān)系,端口就這兩個寄存器TRISIO和GPIO
作者: xxll 時間: 2021-11-27 09:23
#include <pic.h>
#define uchar unsigned char
uchar ON;
void IO_init(void) /*端口初始化*/
{
TRISIO=0x00;
GPIO=0X00;
}
void timer0_init(void) //定時器0初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標(biāo)志
TMR0=224; /*置初值 20KHz的半個周期為25us*/
T0IE=1; //timer0中斷允許
GIE=1; //開全局中斷
}
void interrupt isr(void) //中斷子程序
{
TMR0=224; //定時器0置初值25us
T0IF=0; //清中斷標(biāo)志
if(ON)
{
// TMR0=224; //定時器0置初值25us
// T0IF=0; //清中斷標(biāo)志
GP2=0;
GP1=1;
ON=0;
}
else
{
// TMR0=224; //定時器0置初值25us
// T0IF=0; //清中斷標(biāo)志
GP1=0;
GP2=1;
ON=1;
}
// GP0=~GP0; //GP0位取反
// GP1=!GP0; //使GP1引腳取反GP0
/*在這里廢寢忘食3總天,一度引起孫子的奶奶發(fā)飆
也沒有折騰出正確的結(jié)果*/
}
void main(void) //主程序
{
OSCCONbits.IRCF0=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;//此3條設(shè)置時鐘為8M
IO_init(); //引腳初始化函數(shù)
timer0_init(); //定時器0初始化函數(shù)
GP1=1;
GP2=0;
while(1) //死循環(huán)
{
}
}
花括號里的順序誰在前誰就是窄脈沖,和TMR0、T0IF所在位置無關(guān),但和頻率高低有較大的關(guān)系。稍后我將發(fā)個統(tǒng)計表格上來供大家研究。
-
GAS0002副本.jpg
(112.94 KB, 下載次數(shù): 110)
下載附件
2021-11-27 09:16 上傳
-
GAS0004副本.jpg
(116.43 KB, 下載次數(shù): 150)
下載附件
2021-11-27 09:16 上傳
作者: Y_G_G 時間: 2021-11-27 12:00
你試過增加ANSEL=0x00;這語句沒有?
ANSEL 是要先清除的!
作者: Y_G_G 時間: 2021-11-27 12:25
還要添加一條:
CMCON0=0x07;
作者: xxll 時間: 2021-11-27 19:56
關(guān)于這里的TMRO=224是因?yàn)闀r鐘是8M時設(shè)的值,(256-224)*0.5=16us在8M時鐘時CPU執(zhí)行中斷大約耗費(fèi)9us (后面也證實(shí)了),16+9=25
作者: 188610329 時間: 2021-11-27 20:17
從你發(fā)的手冊上看,
ANSEL 控制引腳是模擬輸入,還是數(shù)字輸出。
如果 有 位置1則為模擬輸入,如果該位置0則為數(shù)字輸出。
手冊上看,上電后 ANSEL 的初值不為0。
并且,手冊上還說,上電后端口初始化 ANSEL 需要 置 0 復(fù)位。
另外,和GPIO有關(guān)的寄存器,總共有11個,
GPIO.png (72.77 KB, 下載次數(shù): 53)
下載附件
2021-11-27 20:12 上傳
此表中,沒有打陰影的部分,都是會影響GPIO的輸出的設(shè)置。
通過此表也能看到,ANSEL 不設(shè)置0的話,GPIO0~GPIO3 默認(rèn)為模擬輸入。
作者: taotie 時間: 2021-11-27 22:34
雖然占空比沒達(dá)到百分之50,但已經(jīng)是互補(bǔ)方波了
屏幕截圖(76).png (259.82 KB, 下載次數(shù): 39)
下載附件
2021-11-27 22:32 上傳
/* 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初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標(biāo)志
TMR0=224; /*置初值 20KHz的半個周期為25us*/
T0IE=1; //timer0中斷允許
GIE=1; //開全局中斷
}
void main(void) //主程序
{
IO_init(); //引腳初始化函數(shù)
timer0_init(); //定時器0初始化函數(shù)
while(1) //死循環(huán)
{
if(flag)
{
GPIO=0B00000001;
}
else
{
GPIO=0B00000010;
}
}
}
void interrupt isr(void) //中斷子程序
{
T0IF=0; //清中斷標(biāo)志
TMR0=224; //定時器0置初值25us
flag = !flag;
}
作者: taotie 時間: 2021-11-28 00:10
本帖最后由 taotie 于 2021-11-29 14:49 編輯
屏幕截圖(111).png (251.1 KB, 下載次數(shù): 41)
下載附件
2021-11-29 14:49 上傳


相差無幾
時鐘8Mhz,標(biāo)志判斷的內(nèi)容由死循環(huán)轉(zhuǎn)到中斷子程序中。
初值設(shè)置為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初始化使用系統(tǒng)默認(rèn)時鐘4M fosc/4 所以計數(shù)周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標(biāo)志
TMR0=225; /*置初值 20KHz的半個周期為25us*/
T0IE=1; //timer0中斷允許
GIE=1; //開全局中斷
}
void main(void) //主程序
{
IO_init(); //引腳初始化函數(shù)
timer0_init(); //定時器0初始化函數(shù)
while(1) //死循環(huán)
{
}
}
void interrupt isr(void) //中斷子程序
{
//T0IF=0; //清中斷標(biāo)志
TMR0=225; //定時器0置初值25us
{
if(flag)
{
GPIO=0B00000001;
}
else
{
GPIO=0B00000010;
}
T0IF=0;
}
flag = !flag;
}
作者: xxll 時間: 2021-12-2 08:22
大家好,由于這幾天忙沒有及時跟帖。在這里謝謝大家對我學(xué)習(xí)的支持,尤其是@ 188610329 和@ Y_G_G 兩位網(wǎng)友老師。在你們細(xì)心的引導(dǎo)下,使我的問題得到正確的答案:端口沒有正確的初始化!是我沒有認(rèn)真細(xì)心的閱讀說明書,造成的后果。只要在IO_init()函數(shù)內(nèi)加入ANSEL=0X00;與CMCON0=0x07;(尤其是CMCON0這個寄存器絕對不能不初始化)我的問題基本就解決了……
-
GPIO端口.jpg
(196.11 KB, 下載次數(shù): 220)
下載附件
2021-12-2 08:19 上傳
作者: xxll 時間: 2021-12-2 08:45
你的程序我也測試了,示波器上的波形不穩(wěn)定,一會正常一會跳變成窄寬不等的波形。還有你這種方式我個人覺得不妥,如果在主程序中加入按鍵掃描和指示燈閃爍,這種方式就更無法正常輸出頻率穩(wěn)定的方波了。你認(rèn)為呢?
作者: xxll 時間: 2021-12-2 11:05
這個波形圖是中斷子程序
void interrupt isr(void) //中斷子程序
{
TMR0=224;
T0IF=0;
GP1=!GP1;
GP2=!GP1;
}
之圖
GP2比GP1滯后3us.jpg (109.91 KB, 下載次數(shù): 233)
下載附件
2021-12-2 10:32 上傳
GP1正脈寬為24.8us,負(fù)脈寬為25.4us,正負(fù)之差0.6uS;GP2比GP1滯后3us
這時GP1與GP2合成的波形即示波器探頭接GP1地夾GP2
GP1與GP2之間合成波形.jpg (103.93 KB, 下載次數(shù): 202)
下載附件
2021-12-2 10:42 上傳
下面是網(wǎng)友
Y_G_G 提供的子程序波形圖
void interrupt isr(void) //中斷子程序
{
TMR0=224; //定時器0置初值25us
T0IF=0; //清中斷標(biāo)志
if(ON)
{
GP2=0;
GP1=1;
ON=0;
}
else
{
GP1=0;
GP2=1;
ON=1;
}
網(wǎng)友正負(fù)脈寬差06us.jpg (102.71 KB, 下載次數(shù): 176)
下載附件
2021-12-2 10:47 上傳
GP1正負(fù)脈寬差也是0.6us,但GP1與GP2合成波延時時差不明顯
網(wǎng)友GP1與GP2合成波.jpg (92.42 KB, 下載次數(shù): 215)
下載附件
2021-12-2 10:51 上傳
下面是一款小產(chǎn)品上測得的波形它的正負(fù)脈寬差只有0.2us
產(chǎn)品副本.jpg (111.26 KB, 下載次數(shù): 201)
下載附件
2021-12-2 10:57 上傳
合成波形很順滑沒有中間的延遲現(xiàn)象
產(chǎn)品2副本.jpg (89.99 KB, 下載次數(shù): 205)
下載附件
2021-12-2 10:59 上傳
到此我又有新的問題要問了:這個產(chǎn)品的波形是怎樣做到呢?
作者: Y_G_G 時間: 2021-12-2 11:26
這GP1和GP0是在同一個端口的嗎?沒有看數(shù)據(jù)手冊,不知道
不同端口的話,那是要兩條指令,那是肯定要有延時的
如果是同一個端口,那就是一條指令就行了if(ON)
{
PORTD=0x01;//假設(shè)是RD端口輸出
ON=0;
}
else
{
PORTD=0x02;
ON=1;
}
作者: xxll 時間: 2021-12-2 11:43
本帖最后由 xxll 于 2021-12-2 12:03 編輯
不是同一端口,原來是GP0與GP1,現(xiàn)在改為GP1與GP2了,其實(shí)道理是一樣的廳
是我理解錯了是同一個端口寄存器,因?yàn)橹挥?個引腳的單片機(jī)。
作者: Y_G_G 時間: 2021-12-2 12:03
GPIO就是一個端口的好不好,直接賦值GPIO端口應(yīng)該就可以得到你要波形了{
GPIO=0x01;//GP0 GP1輸出,自己也可以改其它的IO,如果不想影響其它IO,可以用&
ON=0;
}
else
{
GPIO=0x02;
ON=1;
}
作者: 188610329 時間: 2021-12-2 13:40
老哥,如果你要實(shí)現(xiàn) 產(chǎn)品副本.jpg 那樣的波形的話,你改寫端口的指令必須修改。
void interrupt isr(void) //中斷子程序
{
TMR0=224;
T0IF=0;
GPIO |= 0x06; // 要用字節(jié)改寫 GPIO總線, 而不是用位改寫 IO
}
作者: xxll 時間: 2021-12-2 17:44
你好,這個或運(yùn)算是如何實(shí)現(xiàn)的,我不懂啦。如0x06=0b00000110,若原GPIO=0b00000010或運(yùn)算后它不還是0b00000110嗎?
作者: Y_G_G 時間: 2021-12-2 17:49
GPIO |= 0x06;
這個是不行的,或指令不能輸出低電平的
你自己也要思考一下的嘛
肯定是要用&的嘛
作者: 188610329 時間: 2021-12-2 17:56
Y_G_G 發(fā)表于 2021-12-2 17:49
GPIO |= 0x06;
這個是不行的,或指令不能輸出低電平的
你自己也要思考一下的嘛
打錯了gpio^=0x06
作者: xxll 時間: 2021-12-2 17:58
我不說過我是個門外漢嗎!與我也不會呀
作者: 188610329 時間: 2021-12-2 18:03
xxll 發(fā)表于 2021-12-2 17:44
你好,這個或運(yùn)算是如何實(shí)現(xiàn)的,我不懂啦。如0x06=0b00000110,若原GPIO=0b00000010或運(yùn)算后它不還是0b000 ...
抱歉,是我的鍋,沒復(fù)驗(yàn)就發(fā)了。
應(yīng)該是
gpio ^= 0x06; 與或計算,即1變0,0變1。手機(jī)發(fā)帖排版大小寫就不修改了。
作者: 天ノ憶 時間: 2021-12-2 18:04
GPIO |= 0x06;//這個1,2位輸出高電平,不改變其他位
GPIO &= 0XF9;//這個1,2位輸出低電平,同樣不改變其他位
作者: Y_G_G 時間: 2021-12-2 18:54
門外漢不是理由
與或非編程基礎(chǔ)類知道,不管是你半路出家還是科班出身,不管你專業(yè)人士還業(yè)余愛好,也不管你是長期愛好還是一時性起
這基礎(chǔ)知道是肯定要學(xué)的,如果不想學(xué),那就不要搞單片機(jī)了
不是打擊你,而是沒有基礎(chǔ)的話,那這單片機(jī)玩起來實(shí)在太累了,還浪費(fèi)時間
從你這個問題就可以看出來了,如果當(dāng)初,你多花一個小時的時間去看一下端口設(shè)置,那你就不會在這50%占空比上面花那么多的時間和精力
個人感覺,很多時候,一個自己幾天甚至半個月都搞不定的東西,很有可能只是一個簡單的東西而已,只是自己沒有嚴(yán)謹(jǐn)認(rèn)真的去看相關(guān)的資料而已
我之前就經(jīng)常碰到這樣的問題,一個小小的東西,搞幾天都搞不好,怎么找都找不到問題,最后干脆之前的代碼都不要,從頭再看資料,一步一步的來,一下子就發(fā)現(xiàn)問題了,而且,不過是一個很基礎(chǔ)很簡的問題而已,只是自己老是鉆牛角尖而已
所以,基礎(chǔ)很重要,不管你多大年紀(jì),不管你是出什么目的學(xué)單片機(jī),多看一下基礎(chǔ),不會有壞處
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |