找回密碼
         注冊會員
        搜索附件  
        MCU資訊論壇 附件中心 單片機論壇 AVR單片機論壇 串口實驗范例.rar

        熱門下載

        附件中心&附件聚合2.0
        For Discuz! X2.5 © hgcad.com

        串口實驗范例.rar

         

        串口實驗:
        本程序簡單的示范了如何使用ATMEGA16的USART
        USART的設置
        波特率的計算
        發送采用查詢方式
        接收采用中斷方式
        除非有特殊格式要求,否則不建議使用 printf函數庫,該函數會耗用3~6KB程序空間
        這里的應用比較簡單,所以自己編寫了put_c/put_s函數。
        出于簡化程序考慮,各種數據沒有對外輸出,學習時建議使用JTAG ICE硬件仿真器


        1. #include <avr/io.h>
        2. #include <avr/delay.h>
        3. #include <avr/signal.h>
        4. #include <avr/interrupt.h>

        5. /*
        6. 注: 內部函數_delay_ms() 最高延時  262.144mS@1MHz
        7.     為了使 _delay_ms()函數的延時正確,須在makefile中設定F_CPU為實際的系統時鐘頻
        8.     本范例為7.3728MHz外部石英晶體振蕩器 即 F_CPU=7372800
        9.     因為7.3728MHz能生成多種標準的通訊波特率。
        10.    
        11.     如果使用其他系統時鐘頻率,注意 波特率誤差不要超過 +/-1%.
        12.     做USART通訊時,除非你掌握了校準技術,否則請不要使用內部/外部RC振蕩器
        13. */

        14. //管腳定義
        15. #define PIN_RXD   0  //PD0   RXD
        16. #define PIN_TXD   1  //PD1   TXD
        17. #define LED0   0  //PB0
        18. #define LED1   1  //PB1
        19. #define LED2   3  //PB3
        20. //常量定義
        21. #define BAUDRATE        9600 //波特率
        22. //#define F_CPU   7372800  //這個已經在makefile里面定義了

        23. //宏定義
        24. #define LED0_ON()  PORTB|= (1<<LED0)   //輸出高電平,燈亮
        25. #define LED0_OFF()  PORTB&=~(1<<LED0) //輸出低電平,燈滅
        26. #define LED1_ON()  PORTB|= (1<<LED1)
        27. #define LED1_OFF()  PORTB&=~(1<<LED1)
        28. #define LED2_ON()  PORTB|= (1<<LED2)
        29. #define LED2_OFF()  PORTB&=~(1<<LED2)
        30. //51系列的高電平輸出能力很弱,低電平也僅能點亮LED.所以常見輸出低電平才燈亮的接法。
        31. //AVR芯片的高低驅動能力都很強,甚至能推動8字數碼管的公共極,怎么接都沒問題。

        32. //全局變量
        33. //如果變量會在中斷服務程序中被修改,須加volatile限定
        34. volatile unsigned char FLAG;    //按鍵標志
        35. volatile unsigned char PC_COMMAND;  //PC發出的當前命令
        36. volatile unsigned char RX_BUFFER[16]; //存放接收數據的數組
        37. volatile unsigned char RX_index;   //存放接收數據的個數
        38. //仿真時在watch窗口,監控這些變量。
        39. void put_c(unsigned char c) //發送采用查詢方式
        40. {
        41. while( !(UCSRA & (1<<UDRE)) );
        42. UDR=c;
        43. }
        44. void put_s(unsigned char *ptr)
        45. {
        46. while (*ptr)
        47. {
        48.   put_c(*ptr++);
        49. }
        50. put_c(0x0D);
        51. put_c(0x0A);  //結尾發送回車換行
        52. }

        53. SIGNAL(SIG_USART_RECV) //串口接收中斷服務程序
        54. {
        55. PC_COMMAND=UDR;
        56. switch(PC_COMMAND)
        57. {
        58.   case '0': //0x30 ASCII '0'
        59.    LED0_ON();
        60.    put_s("用戶輸入0#指令");
        61.    break;
        62.   case '1':
        63.    LED1_ON();
        64.    put_s("用戶輸入1#指令");
        65.    break;
        66.   case '2':
        67.    LED0_OFF();
        68.    LED1_OFF();
        69.    FLAG=!FLAG;
        70.    put_s("用戶輸入2#指令");
        71.    break;
        72.   default:
        73.    put_s("用戶輸入的指令無效!");
        74.    break;
        75. }
        76. /*
        77.    注意,使用put_s函數發送數據需要一定的時間,如果輸入數據的速度過高將會導致數據丟失
        78.    所以,一般建議中斷服務程序的處理時間盡量的短,只做采集數據和設標志位,命令的處理交由主程序來完成
        79.    這里只是示范簡單的命令處理
        80. */

        81. RX_BUFFER[RX_index]=PC_COMMAND;  //保存數據到數組里面
        82. RX_index++;
        83. if (RX_index>=16) RX_index=0;  //防止數組溢出
        84.   
        85. }
        86. void init_USART(void)//USART 初始化
        87. {
        88.     //USART 9600 8, n,1  PC上位機軟件(超級終端等)也要設成同樣的設置才能通訊
        89.     UCSRC = (1<<URSEL) | 0x06;
        90.     //異步,8位數據,無奇偶校驗,一個停止位,無倍速
        91.     /*
        92.     UBRRH與UCSRC共用I/O 地址。因此訪問該地址時需注意以下問題。
        93.     寫訪問
        94.     當在該地址執行寫訪問時, USART 寄存器選擇位(URSEL)控制被寫入的寄存器。
        95.     若URSEL為0,對UBRRH值更新;若URSEL為1,對UCSRC設置更新
        96.    
        97.     讀訪問
        98.     對UBRRH 或UCSRC 寄存器的讀訪問則較為復雜。但在大多數應用中,基本不需要讀這些寄存器
        99.    
        100.    
        101.     沒有UBRR這個16位寄存器,因為UBRRL(0x09)/UBRRH(0x20)的地址不連續,而且UBRRH跟UCSRC共用地址
        102.     */
        103.    
        104.     //U2X=0時的公式計算
        105.     UBRRL= (F_CPU/BAUDRATE/16-1)%256;
        106.     UBRRH= (F_CPU/BAUDRATE/16-1)/256;
        107.     //U2X=1時的公式計算
        108.     //UBRRL= (F_CPU/BAUDRATE/8-1)%256;
        109.     //UBRRH= (F_CPU/BAUDRATE/8-1)/256;
        110.     //也可根據數據手冊的[波特率設置的例子]查得
        111.     //UBRRL = 0x2F; //set baud rate lo
        112.     //UBRRH = 0x00; //set baud rate hi
        113.     UCSRA = 0x00;
        114.     UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
        115.     //使能接收中斷,使能接收,使能發送
        116. }
        117. void pro_coammand(void) //多字節命令的處理程序
        118. {
        119. unsigned char i;
        120. if (RX_index>=10)
        121. {
        122.      UCSRB&= ~(1<<RXCIE); //關斷USART接收中斷
        123.   put_c(0x0D);
        124.   put_c(0x0A);  //發送回車換行
        125.   put_s("Hello! 你之前輸入的命令列表是:");
        126.   for (i=0;i<RX_index;i++) put_c(RX_BUFFER[i]);
        127.   put_c(0x0D);
        128.   put_c(0x0A);
        129.   put_c(0x0D);
        130.   put_c(0x0A);  //發送回車換行
        131.   RX_index=0;    //清零
        132.      UCSRB|= (1<<RXCIE); //打開USART接收中斷
        133. }
        134. }
        135. int main(void)
        136. {
        137.     //上電默認DDRx=0x00,PORTx=0x00 輸入,無上拉電阻
        138.     PORTA =0xFF;           //不用的管腳使能內部上拉電阻。
        139.     PORTC =0xFF;
        140.     DDRB  =  (1<<LED2)|(1<<LED1)|(1<<LED0);    //輸出
        141.     PORTB =~((1<<LED2)|(1<<LED1)|(1<<LED0));    //低電平,燈滅
        142.     DDRD  =(1<<PIN_TXD);        //TXD為輸出
        143.     PORTD =0xFF;
        144.     FLAG=0;
        145. init_USART();
        146. put_s("你好!");
        147. put_s("這是一個簡單的串口實驗程序");
        148. put_s("你可以在電腦上的超級終端程按下[0][1][2]按鍵,模擬用戶板上的按鍵操作");
        149.     sei();         //使能全局中斷
        150.     while (1)
        151.     {
        152.         while (FLAG==0) pro_coammand();
        153.         LED2_ON();       //如果FLAG不加volatile限定(即has_volatile=0),程序將永遠都運行不到這里。
        154.         while (FLAG!=0) pro_coammand();
        155.         LED2_OFF();
        156.     }
        157. }
        復制代碼


        程序運行效果
             PC使用超級終端或SSCOM32串口調試程序,發送ASCII碼的簡單方法就是直接按下對應的按鍵
             
             例如  字符'0',即0x30 ,按下鍵盤上的[0]即可
             按下按鍵[0],LED0亮。
             按下按鍵[1],LED1亮。
             按下按鍵[2],LED0/1都熄滅, LED2是根據按鍵[2]的順序來亮滅,是個乒乓鍵

        QQ|手機版|MCU資訊論壇 ( 京ICP備18035221號-2 )|網站地圖

        GMT+8, 2025-3-16 21:39 , Processed in 0.023585 second(s), 8 queries , Redis On.

        Powered by Discuz! X3.5

        © 2001-2024 Discuz! Team.

        返回頂部
        国产91精品一区二区麻豆亚洲| 中文字幕无码精品三级在线电影| 亚洲AV永久无码精品一百度影院| 无码国产精品一区二区免费式芒果| 国产精品国产亚洲精品看不卡| 92国产精品午夜福利免费| 国产午夜精品久久久久九九电影| 综合精品欧美日韩国产在线| 国产欧美日韩精品a在线观看| 成人精品一区二区三区| 欧美亚洲成人精品| 久久99精品久久只有精品| 欧美精品天天操| 精品久久久久久无码人妻蜜桃| 又爽又大又黄a级毛片在线视频 | 亚洲精品乱码久久久久久不卡| 欧美精品亚洲精品日韩传电影| 99久久精品免费观看国产| 亚洲国产精品成人| 91国在线啪精品一区| 久久精品国产WWW456C0M| 久久亚洲中文字幕精品有坂深雪| 91不卡在线精品国产| 免费吃奶摸下激烈视频青青网| 国产午夜精品理论片久久影视 | 精品深夜AV无码一区二区| 国产成人精品综合久久久| 亚洲无线观看国产精品| 中文字幕精品一区影音先锋| 国内精品久久久久影院薰衣草| 2021最新国产精品一区| 老湿司午夜爽爽影院榴莲视频| 国产亚洲精品a在线观看app| 亚洲精品国产电影| 久久久精品午夜免费不卡| 久久中文字幕亚洲精品最新| 99久re热视频这里只有精品6| 亚洲精品无码久久久久| 国产高清在线精品一区二区 | 国产AV国片精品一区二区| 亚洲精品无码永久在线观看你懂的|