![]() |
發布時間: 2025-1-15 22:43
正文摘要:/**本程序用于測試分散I/O口驅動4位數碼管顯示**/ #include <STC12C5A60S2.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char //----I/O口位功能定義---------------- ... |
你確定首發的圖正確?CPU處是P0口輸出數據,數碼管處是用了p0;p1???? |
hjx5548 發表于 2025-1-24 05:11 //====主函數============================================== void main() { P1M0 = 0x00; P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; while(1) { display_out(34); Delay5ms(); } } |
hjx5548 發表于 2025-1-24 05:11
|
hjx5548 發表于 2025-1-24 05:11 為何要做定時器中斷里面調用display_out(34);? |
hjx5548 發表于 2025-1-24 05:11 發原理圖全圖 |
hjx5548 發表于 2025-1-24 07:55 上傳代碼要用代碼功能,就是上邊的那個中括弧 |
segment_out(duan_ma[date[i]]);//上傳怎么沒有了 |
WL0123 發表于 2025-1-23 14:55 #include "STC8G.h" #include <intrins.h> #define uint unsigned int #define uchar unsigned char //----I/O口段定義----------------------------------- sbit da=P3^7; sbit db=P3^2; sbit dc=P3^3; sbit dd=P3^5; sbit de=P3^4; sbit df=P3^6; sbit dg=P1^1; sbit dp=P1^0; //不含小數點8段LED字形碼0-9+黑屏碼、共陽極驅動0亮1熄 uchar duan_ma[11]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; uchar date[4];//顯示數據暫存 bit flag; void Delay1ms(void) //@11.0592MHz { unsigned char data i, j; i = 15; j = 90; do { while (--j); } while (--i); } void Timer0_Init(void) //1毫秒@12.000MHz { AUXR |= 0x80; //定時器時鐘1T模式 TMOD &= 0xF0; //設置定時器模式 TL0 = 0x20; //設置定時初始值 TH0 = 0xD1; //設置定時初始值 TF0 = 0; //清除TF0標志 TR0 = 1; //定時器0開始計時 ET0=1; EA=1; } //======================================================= //將LED字形的8個筆段控制I/O引腳映射到變量的8個位上 void segment_out(uchar dat) { da=(bit)(dat&0x01); db=(bit)(dat&0x02); dc=(bit)(dat&0x04); dd=(bit)(dat&0x08); de=(bit)(dat&0x10); df=(bit)(dat&0x20); dg=(bit)(dat&0x40); dp=(bit)(dat&0x80); } //====數據拆分函數======================================= //提取出數據的千、百、十、個位的數值存入數組中 void digits_obtain(uint dat) { date[0]=dat/10; date[1]=dat%10; } //====顯示輸出函數======================================= void display_out(uint dat) { static uchar i; digits_obtain(dat);//拆分數據 segment_out(0xff);//段碼清除(消隱) if(i==0) {P55=0;P12=1;}//十位 else {P55=1;P12=0;}//個位 segment_out(duan_ma[date]);//發送段顯示碼 // i=++i%2; if (++i>=2) i=0; } //====主函數============================================== void main() { P1M0 = 0x00; P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; Timer0_Init(); Delay1ms(); while(1) { if(flag)//5ms { flag=0; // display_out(34); } } } void Timer0Interrupt(void) interrupt 1 { display_out(34); flag=1; } 還是顯示9 |
WL0123 發表于 2025-1-23 14:55 端口模式已經設置void main() { P1M0 = 0x00; P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; |
//====顯示輸出函數======================================= void display_out(uint dat) { static uchar i; digits_obtain(dat);//拆分數據 segment_out(0xff);//段碼清除(消隱) if(i==0) {P55=0;P12=1;}//十位 else {P55=1;P12=0;}//個位 segment_out(duan_ma[date]);//發送段顯示碼 i=++i%2; } 還是一樣 |
hjx5548 發表于 2025-1-23 07:04 如果MCU采用的還是STC12C5A60S2不需要設置端口模式,默認是準雙向。沒有P55,就在P50~53選一個空閑腳或其它空閑腳。你那十位顯示9其實是3和4的疊加。換芯片STC8G1K08,需要設置端口模式,因為默認是高阻。定時器用自動重裝模式為好。上述兩款單片機可以直接驅動數碼管,不需要加晶體管放大。數碼管段驅動要加8個限流電阻。 |
![]() ![]() |
WL0123 發表于 2025-1-22 11:30 修改一下,十位顯示9,個位無顯示。 /*hjx5548 發表于 2025-1-21 22:13 如果這樣怎么修改 如果MCU采用的還是STC12C5A60S2那就沒有P55,只有P50~53。示例程序:*/ //#include <STC12C5A60S2.h> #include "STC8G.h" #include <intrins.h> #define uint unsigned int #define uchar unsigned char //----I/O口段定義----------------------------------- sbit da=P3^7; sbit db=P3^2; sbit dc=P3^3; sbit dd=P3^5; sbit de=P3^4; sbit df=P3^6; sbit dg=P1^1; sbit dp=P1^0; //不含小數點8段LED字形碼0-9+黑屏碼、共陽極驅動0亮1熄 uchar duan_ma[11]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; uchar date[4];//顯示數據暫存 bit flag; void Timer0_Init(void) //5毫秒@11.0592MHz { AUXR |= 0x80; //定時器時鐘1T模式 TMOD &= 0xF0; //設置定時器模式 TL0 = 0x00; //設置定時初始值 TH0 = 0x28; //設置定時初始值 TF0 = 0; //清除TF0標志 TR0 = 1; //定時器0開始計時 ET0=1; EA=1; } //======================================================= //將LED字形的8個筆段控制I/O引腳映射到變量的8個位上 void segment_out(uchar dat) { da=(bit)(dat&0x01); db=(bit)(dat&0x02); dc=(bit)(dat&0x04); dd=(bit)(dat&0x08); de=(bit)(dat&0x10); df=(bit)(dat&0x20); dg=(bit)(dat&0x40); dp=(bit)(dat&0x80); } //====數據拆分函數======================================= //提取出數據的千、百、十、個位的數值存入數組中 void digits_obtain(uint dat) { date[0]=dat/10; date[1]=dat%10; } //====顯示輸出函數======================================= void display_out(uint dat) { static uchar i; digits_obtain(dat);//拆分數據 segment_out(0xff);//段碼清除(消隱) if(i==0) {P55=0;P12=1;}//十位 else {P55=1;P12=0;}//個位 segment_out(duan_ma[date]);//發送段顯示碼 i=++i%2; } //====主函數============================================== void main() { P1M0 = 0x00; P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; Timer0_Init(); while(1) { if(flag)//5ms { flag=0; display_out(34); } } } void Timer0Interrupt(void) interrupt 1 { TL0 = 0x00; //設置定時初始值 TH0 = 0x28; //設置定時初始值 flag=1; } |
WL0123 發表于 2025-1-22 11:30 芯片是STC8G1K08 |
hjx5548 發表于 2025-1-21 22:13 如果MCU采用的還是STC12C5A60S2那就沒有P55,只有P50~53。示例程序:
|
xiaobendan001 發表于 2025-1-16 12:46 這個我試了,你是對的,沒有錯 |
數碼管顯示異常是樓主的數碼管位驅動碼錯誤所致。修改如下:
|
jjy1039 發表于 2025-1-16 08:59 有沒有試過?軟件模擬也能看到的 |
da=(bit)(duan_ma[dat]&0x01); ....... |
單片機研究協會 發表于 2025-1-16 01:10 位域怎么寫,請大俠指點一二 |
1、先排除掉硬件問題,接線問題。2、直接用高低電平試試每一段是不是都能點亮。然后用程序控制。邏輯上不要有沖突。 |
新愛的壇友,你確定你的代碼沒有問題嗎!你確定你已經編譯通過了嗎! LINE 96 segment_out(duan_ma[date]); //發送段顯示碼 LINE 97 position_out(wei_ma); //發送位顯示碼 這兩行代碼重點檢查一下...... |
segment_out(duan_ma[date]); //發送段顯示碼 [date] 默認是地址 0 ,所以只顯示0 修改:date[i] |
96行, segment_out(duan_ma[date]); 其中date是數組類型,改為segment_out(duan_ma[i ]) |
DATE是個數組,你把它當做下標是幾個意思。你是不是應該這樣duan_ma[date[i]]; 還有wei_ma也有問題。是不是也應該寫成wei_ma[i];, |
有兩點可以優化 1:改用共陰數碼管,可以省三極管 2:改用位域操作 |