音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

登錄 免費注冊 首頁 | 行業(yè)黑名單 | 幫助
維庫電子市場網(wǎng)
技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng)
驅(qū)動編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機 | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計 | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe

一次程序編寫筆記:簡潔的提示音程序(附代碼及說明)

作者:winsu 欄目:單片機
一次程序編寫筆記:簡潔的提示音程序(附代碼及說明)
=====前提=====
有些項目要驅(qū)動蜂鳴器,復(fù)雜點時,蜂鳴器就有好幾種鳴響方式。
如"bi------"長鳴;
"bi.bi.bi."短促提示音;
"bi.........bi.........."慢的提示音;
用單片機控制蜂鳴發(fā)出滿足以上要求當然并不是難事。但要做到最簡潔,所用資源最小,卻是考人的。
本人開始所寫程序較長,近來重寫程序,用大半天時間分析提示音,終于可用最簡潔的程序?qū)崿F(xiàn)相同的功能。

=====題目=====
總結(jié)一下,出個題目,考一下大家的編寫程序能力。
用單片機驅(qū)動蜂鳴器,要求蜂鳴器響時間與間隔時間可任意設(shè)定。用一函數(shù)實現(xiàn),參數(shù)是時間設(shè)置,返回蜂鳴器開關(guān)值。如:
CHAR soud_pulse_gap(CHAR on, CHAR off)
{
      ...
}
on是蜂鳴器響時間,off是關(guān)時間,返回蜂鳴器當前開關(guān)狀態(tài)。該函數(shù)在主程序中每隔例如30ms執(zhí)行一次。假設(shè)已經(jīng)有蜂鳴器驅(qū)動函數(shù):
void soud_on(CHAR on);
則在系統(tǒng)中這樣引用:
void main(void)
{
      ......;
      soud_on(soud_pulse_gap(1, 3));
      //其他程序執(zhí)行30ms
      ......;
}
以上程序?qū)崿F(xiàn)“響30ms停90ms響30ms停90ms......"的功能。
請各位大俠寫出函數(shù)CHAR soud_pulse_gap(CHAR on, CHAR off)的內(nèi)容。遲點本人會附上自己寫的。

=====程序=====
用簡潔的方法寫出發(fā)音函數(shù),其實只有兩句,不知是不是最簡單的。
程序中涉及以下定義:
typedef unsigned CHAR       u8;
typedef unsigned int        u16;
“bi.bi.bi”提示音的產(chǎn)生,參數(shù)on為響時間,off為間隔,返回聲音的開或關(guān)
u8 sd_pulse_gap(u8 on, u8 off)
{
    static u16 cnt;
    return ((cnt++ % (on + off)) < on);
}
聲音的開與關(guān),我使用AVR單片機,用CTC方式產(chǎn)生音頻
void sd_audio_on(u8 on)
{
    ......;
}
在程序中可象上面所說的引用
void main(void)
{
      ......;
      sd_audio_on(soud_pulse_gap(1, 3));
      //其他程序執(zhí)行25ms
      ......;
}

=====原理=====
或許有些人對這句程序:
return ((cnt++ % (on + off)) < on);
有不明白之處,其實如果不作注釋,甚至沒有相關(guān)說明文檔,時間長后自己也記不起了。
首先我用些時間分析一下聲音的規(guī)律,在我的項目中有幾種聲音模式,用圖形把它畫出來,如下圖:

Excel文件:http://bbs.21ic.com/upfiles/img/200611/2006111002058205.rar
其中T0是長鳴,T6是不響。
這是在excel中畫的,并把它數(shù)字化,最后就可轉(zhuǎn)化成程序 [ 如果程序都這樣簡單,低手立即變高手了 :)
原理基本過程是這樣:我們需要一個計數(shù)器來作為節(jié)拍,其實就象單片機中的時鐘。然后把這個“時鐘”進行“分頻”,再根據(jù)需要在某處為“1”某處為“0”,“1”即響;“0”即停。
第一行紅色數(shù)字就是”時鐘“,每個波形圖上面的藍色數(shù)字就是”分頻“后的結(jié)果,面下面的黑色數(shù)字是最后結(jié)果。也就是((cnt++ % (on + off)) < on)得出的結(jié)果。

=====應(yīng)用=====
要實現(xiàn)圖中T0~T6,可用以下的程序,這里用“緩沖”簡化程序,“農(nóng)民講習(xí)所”的拿手好戲(若說得不對,請勿見怪)
提示音數(shù)據(jù),7種提示音,包括長鳴與不響.第1列是鳴(1=25ms),第2列是滅(1=25ms)
const u8 sd_tone][7][2] = {
    { 11,0 },
    { 1,2 },
    { 1,3 },
    { 2,4 },
    { 2,5 },
    { 1,10 },
    { 0,11 },
};
T0~T6各種提示音模式
void sd_main(u8 tone)
{
    sd_audio_on(sd_pulse_gap(sd_tone[tone][0], sd_tone[tone][1]));
}
也可用一維數(shù)據(jù)代替二維數(shù)據(jù)。

=====總結(jié)=====
再啰嗦一下,重寫一次程序,可”長一智“。
1)多用算法,少用”程序“;
2)寫程序前先分析,可借助一些自己熟悉的工具。
3)適當用”緩沖“,可簡化程序。
......

* - 本貼最后修改時間:2006-11-10 0:36:47 修改者:winsu

2樓: >>參與討論
conwh
這里拽的人是越來越多了
 
3樓: >>參與討論
IceAge
不用這么麻煩吧。
用狀態(tài)機的原理:

SWITCH (status) {
  case 0: break;  // stop;

  case 1:
     sound_on();  // 響 30 ms
     status++;
     break;

  case 2:
     sound_off();
     timer = SOMEVALUE;  //or from an array, 停 N ms
     status++;
     break;
  
  case 3:     // delay for off
     timer--;
     if (timer != 0) break;
     sound_on();
     timer = ANOTHERVALUE;  //or from an array,  響 N ms  
     status++;
     break;

  case 4:  //delay for on
    ...
    status -= 2;   //goto status 2

原理大致如此, 細節(jié)和形式可以不同,例如如果僅僅幾種聲音,所有延時都在 SWITCH-case 里,如果需要靈活性,那么可以使用數(shù)組甚至隊列。 又比如:
  case 4:
  case 5:
  case 6:
     status++; break;   
  case 7:
     sound_off()    // delay 120 ms
     
     
  


4樓: >>參與討論
wangkj
又不是多任務(wù),用for循環(huán)就得了。
復(fù)雜點就用中斷,計是器

5樓: >>參與討論
zhiwei
這也太復(fù)雜了吧
用一個8bit或16bit位數(shù)據(jù)來移位輸出就可以了,以30mS為時基來中斷處理就可以了,占用CPU很少。30mS的定時由系統(tǒng)的Tick提供。

6樓: >>參與討論
農(nóng)民講習(xí)所
簡單的
unsigned CHAR code cBZTime[]={
    3,1,  //on,off
    3,1,
   .......
    0
};


unsigned CHAR mTaskId;
unsigned CHAR mTimer;

void BZ_Loop(void)
{
if( 系統(tǒng)30MS到 ){
    if( mTimer ){
       //有BZ任務(wù)
       if( --mTimer == 0 ){
           //改變輸出狀態(tài)
           mTimer = cBZTime[++mTaskId];
           IO_BZ_Change();
       }
    }
}
}

void BZ_On(void)
{
   mTaskId=0;
   mTimer = cBZTime[0];
}

void BZ_Off(void)
{
  mTimer = 0;
}

所有功能執(zhí)行都在狀態(tài)變化時刻執(zhí)行,外部程序有最大執(zhí)行時間。


* - 本貼最后修改時間:2006-11-9 9:32:35 修改者:農(nóng)民講習(xí)所

7樓: >>參與討論
xwj
哈哈,“響30ms停90ms響30ms停90ms......”LZ你自己聽過效果嗎?
很簡單的東西,而且一般是幾長幾短的響,誰會這樣響去?

象2這種小東西,
不是接近0資源占用的都不是好程序

8樓: >>參與討論
winsu
感謝各位回復(fù)
農(nóng)民講習(xí)所也來了,用"緩沖法"來簡化程序,我可是學(xué)你的.

conwh: 哪里看得出我"拽"?

xwj: 我說的有什么錯處嗎?請?zhí)岢?我作出修改.我是指寫一個任何方式響的程序,至于“響30ms停90ms響30ms停90ms......”只是例子,效果如何就看情況了.我的應(yīng)用并不是這樣,但只是時間不同.

zhiwei: 不用中斷,計時器等資源.

9樓: >>參與討論
NE5532
又沒說是多任務(wù)系統(tǒng)啊
開,延遲,關(guān),延遲……可否?

10樓: >>參與討論
winsu
這只是項目中的一個函數(shù)
不管是否多任務(wù),反正單片機不是只做這項工作.
它越省就越好.

正如xwj所說:
"象2這種小東西,
不是接近0資源占用的都不是好程序"


11樓: >>參與討論
huangqi412
高人真多,學(xué)習(xí)了
 
12樓: >>參與討論
oyggj
這個有意思.
這個有意思.

13樓: >>參與討論
conwh
拽的來源:
考者,為先人、長者和智者;被考者為學(xué)生。LZ出個簡單題目來考大家,難道不是“拽”,呵呵。

14樓: >>參與討論
happystar
恩,我們這里屬于干凈的一片天。
我在單位研發(fā)部工作,在這里大家談?wù)摰亩际羌夹g(shù),像我們這些小輩們有不懂的地方只管問老工程師。每天辦公室里就是幾壺?zé)崴筒枞~。大家以做技術(shù)為樂,很是清閑。老板也是比較尊重我們的,不像對待其他部門的人一樣。他也是做技術(shù)出生,只不過現(xiàn)在沒時間干這些拉。他一有時間就過來和我們談技術(shù)什么的,還經(jīng)常談他以前做過的項目怎樣怎樣。
嘿嘿,我本來是個比較內(nèi)向的人,我覺得自己正適合這樣的工作?傊杏X我們這一行少了社會的紛雜?吹竭@個帖子,我也感覺這邊也很純潔。
嘿嘿,我語文不好,不回組織語言,大家理解我意思就行拉

15樓: >>參與討論
IceAge
conwh 老弟不必如此。技術(shù)討論,如同 happystar 所說,
應(yīng)單純些,更何況 winsu 還寫了那么長。

就 “響30ms停90ms響30ms停90ms“而言,最簡潔我想莫過于采用 state machine, 可以不使用任何條件判斷,C 下面用 SWITCH-case 不算明顯,匯編下使用散轉(zhuǎn)非常簡潔。此塊每 30 ms 進入一次:
SWITCH (state) {
    case 0: break;
    case 1: sound_on(); state++; break;
    case 2: sound_off();
    case 3: state++; break;
    case 4: state =1; break;

程序行數(shù)雖比所長多,但更直截了當。程序任何地方可以通過 state = 1 啟動,state = 0 停止。 

16樓: >>參與討論
winsu
關(guān)于“考”
或許我用“考”字的語氣太重,請conwh勿太在意。我查了一下字典,并沒說明要先人、長者和智者考學(xué)生的。
并且,我有資格考別人,特別是比我年齡小的。但“農(nóng)民講習(xí)所”等我就沒資格考了。
這單純是技術(shù)討論,請勿涉及以個人人格問題,如果我用詞不當,請指出,我會改過。

17樓: >>參與討論
winsu
我寫的程序
這是我寫的程序:
u8 sd_pulse_gap(u8 on, u8 off)
{
    static u16 cnt;
    return ((cnt++ % (on + off)) < on);
}
更詳細說明請看樓主位置原文

* - 本貼最后修改時間:2006-11-10 12:56:42 修改者:winsu

18樓: >>參與討論
abszero
頂住了看看
 
參與討論
昵稱:
討論內(nèi)容:
 
 
相關(guān)帖子
關(guān)于8255擴展鍵盤問題!
問個Xilinx ISE 8.2i的問題
求教,兩次買的18B20為什么性能不一樣。
長虹遙控板
AT89S52用Easy 51Pro通過ISP下載線寫數(shù)據(jù)報錯,請問是什么原因
免費注冊為維庫電子開發(fā)網(wǎng)會員,參與電子工程師社區(qū)討論,點此進入


Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號