【项目】STC15W408AS--烧写、数码管、按键、串口通信、ADC
目錄
1、燒錄
2、數碼管—共陽極
3、按鍵—長按+短按
4、串口通信—TXD+RXD
5、ADC
6、總結
1、燒錄
燒錄環境:STC-ISP(善用這個軟件,里面有STC系列芯片豐富的示例程序)
燒錄工具:使用usb轉ttl模塊(CH340)
燒錄過程:將TXD、RXD、GND都接好后,先不接5V,連上電腦,識別到串口后,打開程序文件(之前要生成hex文件),點擊下載/編程,這時程序顯示正在檢測單片機,然后把5V接到單片機,程序就燒錄成功了。
2、數碼管—共陽極
電路
要注意區別共陽和共陰的區別。這里以共陽極為例。
原理:淺薄的來說一下我自己的理解,一個數碼管主要由位選和段選來控制。對于一位(即一個8)而言,我們將它所有led的陽極都連接在一起,這一端即位選,用于接5V電路,即上圖的DIG1。然后我們把led的陰極與單片機引腳相連接,這一端即段選,即A、B、C...當單片機引腳輸出0,led的陽極到陰極導通,led發光,數碼管亮,這就是共陽極數碼管基本的運行原理。
R19、R20、R21的作用:?
R13~R18..的作用:?(應該都是起到保護作用吧)
一個建議:最好將8位段選都放在mcu的一個口上,如P2口,這樣寫程序的時候方便點。
代碼
#include "led.h" ? u8 table[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //顯示0~F ? //位選 sbit dig1=P3^4; sbit dig2=P3^3;//十位 sbit dig3=P3^2;//個位 ? ? //數碼管顯示 void display(u16 i){ ?u16 ge = i%10;u16 shi = i%100/10;u16 bai = i/100;//顯示個位dig1 =1;dig2 =1;dig3 =0;show(ge);delay(5);//顯示十位dig1 =1;dig2 =0;dig3 =1;show(shi);delay(5);//顯示百位dig1 =0;dig2 =1;dig3 =1;show(bai);delay(5); } ? ? void show(u16 i){ P2 = table[i]; } -------------------------------------------------------------------- #ifndef __LED_H #define __LED_H ? #include <stc15.h> #include "global.h" ? //#define uchar unsigned char //#define uint unsigned int ? extern u8 table[16]; ? ? //void delay(u16 z); void display(u16 i); void show(u16 i); ? #endif3、按鍵—長按+短按
電路
蠻簡單的,只要單片機有個口去檢測電平變化即可,我是接到外部中斷口上去了,在下降沿的時候觸發按鍵的判斷,都可以。(CHECK_KEY)
代碼
因為在檢測按鍵的時候,數碼管也需要同時運行,所以不能簡單的在函數里加個delay來延時,這樣會導致進程阻塞,數碼管不工作,所以我把按鍵判斷放在了定時器中斷里(定時器0在這個程序中是一直在跑著的)賦值key,然后去做相應的動作。
//定時器0中斷服務程序-按鍵 ? 5毫秒@11.0592MHz (實際是50ms左右) void tm0_isr() interrupt 1 {extern u16 KEY_PIN;if(KEY_PIN){key_count2++;//本意是消抖,但這里好像有點多余,可能條件換成P37==0更好}if(key_count2>=2){ if(P37 == 0){press_flag = 1;KEY_COUNT++;}else{ if(press_flag){if(KEY_COUNT>=60){KEY_COUNT = 0;press_flag = 0;key = 0; //長按KEY_PIN = 0;key_count2 = 0; }else{KEY_COUNT = 0;press_flag = 0;key = 1; //短按 KEY_PIN = 0; key_count2 = 0;} }} } } /*外部中斷3僅下降沿可以觸發。外部中斷2~3的中斷請求標志位被隱藏起來了,對用戶不可見,故也無需用戶清"0"。當相應的中斷服務程序被響應后或中斷允許位EXn (n=2,3)被清零后, 這些中斷請求標志位會立即自動地被清0。*/ //----------------------------------------------- //外部中斷3服務程序(僅下降沿觸發) void exint3() interrupt 11 ? ? ? ? ?//INT3中斷入口 {extern u16 KEY_PIN;KEY_PIN = 1; ? // INT_CLKO &= 0xDF; ? ? ? ? ? ? ? //若需要手動清除中斷標志,可先關閉中斷,此時系統會自動清除內部的中斷標志 // INT_CLKO |= 0x20; ? ? ? ? ? ? ? //然后再開中斷即可 } //定時器初始化 #define FOSC 11059200L #define T5MS (65536-5*FOSC/1000) ? ?//1T模式,110592MHzINT_CLKO |= 0x20; ? ? ? ? ? ? ? //(EX3 = 1)使能INT3中斷,僅下降沿觸發 AUXR |= 0x80; ?//定時器時鐘1T模式 (定時器0的速度是傳統8051的12倍,不分頻)//AUXR &= 0x7f; ? ? ? //定時器0為12T模式TMOD &= 0xF0; ?//設置定時器模式(16位自動重裝定時器)TL0 = T5MS; ? ? ? ? ? //初始化計時值TH0 = T5MS >> 8;TF0 = 0; ?//清除TF0標志(溢出中斷標志)TR0 = 1; ?//定時器0開始計時ET0 = 1; ? ? ?//使能定時器0中斷EA = 1; ?//打開總中斷4、串口通信—TXD+RXD
電路
代碼
也差不多都是例程里的代碼,具體怎么實現就看你自己啦。
#include "uart.h" ? #define FOSC ? 11059200L #define BAUD ? 115200 ? #define ? ? URMD ? 0 ? ? ? ? ? //0:使用定時器2作為波特率發生器//1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器//2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器 ? ? /*---------------------------- 初始化串口 ----------------------------*/ void InitUart() {SCON = 0x5a; ? ? ? ? ? ? ? ?//設置串口為8位可變波特率 #if URMD == 0T2L = (65536 - (FOSC/4/BAUD));T2H = (65536 - (FOSC/4/BAUD)) >> 8;AUXR = 0x14; ? ? ? ? ? ? ? ?//T2為1T模式, 并啟動定時器2AUXR |= 0x01; ? ? ? ? ? ? ? //選擇定時器2為串口1的波特率發生器ES = 1; ? ? ? ? ? ? ? ? ? ? //使能串口1中斷 #elif URMD == 1AUXR = 0x40; ? ? ? ? ? ? ? ?//定時器1為1T模式TMOD = 0x00; ? ? ? ? ? ? ? ?//定時器1為模式0(16位自動重載)TL1 = (65536 - (FOSC/4/BAUD)); //設置波特率重裝值TH1 = (65536 - (FOSC/4/BAUD)) >> 8;TR1 = 1; ? ? ? ? ? ? ? ? ? ?//定時器1開始啟動 #elseTMOD = 0x20; ? ? ? ? ? ? ? ?//設置定時器1為8位自動重裝載模式AUXR = 0x40; ? ? ? ? ? ? ? ?//定時器1為1T模式TH1 = TL1 = (256 - (FOSC/32/BAUD));TR1 = 1; #endif } ? /*---------------------------- 發送串口數據 ----------------------------*/ void SendData(u8 dat) {SBUF = dat; ? ? ? ? ? ? ? ? ? ? //發送當前數據while (!TI); ? ? ? ? ? ? ? ? ? ?//等待前一個數據發送完成TI = 0; ? ? ? ? ? ? ? ? ? ? ? ? //清除發送標志 ? } ? /**************************************************函數名稱:void Uart() interrupt 4 using 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*功 ? 能:串口中斷處理函數 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*參 ? 數:void ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *返 回 值:void ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *************************************************/ void Uart() interrupt 4 using 1 {//接收中斷標志if(RI){RI = 0; ? ? ? ? ? ? ? ? //清除RI位ReceiveBuf = SBUF;if(ReceiveDone == 0){} }//發送中斷標志if (TI) //8位數據發送結束 會請求中斷{TI = 0; ? ? ? ? ? ? ? ? //清除TI位// busy = 0; ? ? ? ? ? ? ? //清忙標志} }5、ADC
電路:
代碼
獲取ADC結果后就可以按你需要的想法去操作了。
它返回的結果是內部已經計算好的,公式大概記得是256*(vin/vcc)。參考電壓是你的電源電壓。
#include "adc.h" #include "intrins.h" ? /* --- STC15F4K60S4 系列 AD轉換查詢方式舉例----------------------------*/ ?? #define ADC_POWER ? 0x80 ? ? ? ? ? ?//ADC電源控制位 #define ADC_FLAG ? 0x10 ? ? ? ? ? ?//ADC完成標志 #define ADC_START ? 0x08 ? ? ? ? ? ?//ADC起始控制位 #define ADC_SPEEDLL 0x00 ? ? ? ? ? ?//540個時鐘周期轉換一次,模數轉換器轉換速度控制位 #define ADC_SPEEDL 0x20 ? ? ? ? ? ?//360個時鐘 #define ADC_SPEEDH 0x40 ? ? ? ? ? ?//180個時鐘 #define ADC_SPEEDHH 0x60 ? ? ? ? ? ?//90個時鐘 ? /*---------------------------- 讀取ADC結果 ----------------------------*/ u8 GetADCResult(u8 ch) {ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;_nop_(); ? ? ? ? ? ? ? ? ? ? ? ?//等待4個NOP_nop_();_nop_();_nop_();while (!(ADC_CONTR & ADC_FLAG));//等待ADC轉換完成ADC_CONTR &= ~ADC_FLAG; ? ? ? ? //Close ADC,ADC_FLAG清零 ?return ADC_RES; ? ? ? ? ? ? ? ? //返回ADC結果(256*(vin/vcc)) } ? ? /*---------------------------- 初始化ADC ----------------------------*/ void InitADC() {P1ASF = 0xc0; ? ? ? ? ? ? ? ? ? //設置P1口為AD口 (設置p1.0和p1.1口為ad口)ADC_RES = 0; ? ? ? ? ? ? ? ? ? ?//清除結果寄存器ADC_CONTR = ADC_POWER | ADC_SPEEDLL;Delay(2); ? ? ? ? ? ? ? ? ? ? ? //ADC上電并延時 }6、總結
從選型到全部跑通,這個小項目大概做了一個月,第一次上手51單片機(本科學過但已經很模糊了)很感謝自己選了STC這個品牌,雖然看它的官網看著非常的難以言喻(沒有不好的意思),但它的上位機做的是真的好,stc-isp,基本上從單片機的選型、添加型號到keil里,以及豐富的例程都給我提供了非常多的幫助。推薦給大家。完整的項目資源如下。
【項目】STC15W408AS--燒寫、數碼管、按鍵、串口通信、ADC-嵌入式文檔類資源-CSDN文庫
未完待續...
感謝指導!
總結
以上是生活随笔為你收集整理的【项目】STC15W408AS--烧写、数码管、按键、串口通信、ADC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: form表单样式
- 下一篇: eeupdate使用说明_Fedora如