5、数码管驱动使用
一、判斷現(xiàn)在手里頭買的是共陰還是共陽數(shù)碼管
我們可使用萬用表進行最簡單判斷,將萬用表調到二極管檔,
(1)萬用表筆隨便一腳,假設紅筆, 搭在數(shù)碼管上任一腳 。黑筆在其它腳上掃過,如果不亮,有可能此管為共陰,可用2法再試。如有一段點亮。黑筆不動, 移動紅筆,在其它腳測。如果其它腳 分別都 能點亮,則可以說明黑筆接的是公共腳 ,此管共陽。(指針 表的黑表筆是正電源)
(2)表筆更換一下,黑筆先搭一腳,掃紅筆。如有一段點亮,紅筆不動,掃黑筆。如各段分別點亮,則紅筆所接為公共 ,此管共陰
二、段選與位選
多位一體數(shù)碼管,內部的公告端是獨立的,我們把公共端叫做位選線
負責顯示什么數(shù)字的線全部都是連接在一起,我們把這個叫做段選線
三、現(xiàn)在使用大部分都直接使用驅動芯片了,所以我們重點來講驅動芯片的使用
網(wǎng)上搜一搜 ,比如tm1650就是一個8*4驅動,可以驅動4位數(shù)碼管,采用的IIC通訊
當時開發(fā)用的中微的芯片,所以在此我就拿中微的CMS1650來寫,其實他跟TM1650都是一樣的,數(shù)碼管驅動芯片大同小異,掌握一款其他就都會了。
三、CMS1650
1、概述
方便使用,電路設計便捷,工作電壓又低,堪稱完美
2、管腳
管腳分布圖DIG就是位選,其他就是段選
3、通訊協(xié)議
通訊協(xié)議采用的是IIC通訊協(xié)議。我們可以看看規(guī)格書,規(guī)格書我上傳了。
(1)先來看看規(guī)格書寫的協(xié)議的開始的信號與停止信號
啟始信號,在SCL為高電平期間,SDA出現(xiàn)下降沿現(xiàn)象;
考慮代碼整潔性,我們可以先進行宏定義
#define CLS_CMS_SCL ? P0_4 = 0 ? //時鐘拉低
#define SET_CMS_SCL ? P0_4 = 1 ? //時鐘拉高?
#define SET_CMS_SDA ? P0_5 = 1 ? //數(shù)據(jù)拉低
#define CLS_CMS_SDA ? P0_5 = 0 ? //數(shù)據(jù)拉高
#define CLK ? ? ? ? ? P0_4 ?
#define SDA ? ? ? ? ? P0_5 ?
#define SDA_OUT() ? ? {P0TRIS |= 0x20;P0 |= 0x20; }?
#define SDA_INT() ? ? {P0TRIS &= 0xDF;P0UP |=0x20;}
void LED_Init(void)
{
? P0TRIS |= 0x10; //設置P04輸出 SCL
?? ?P0 |= 0x10; ? ? //輸出高?? ?
?
?? ?P0TRIS |= 0x20; //設置P05輸出 SDA
?? ?P0 |= 0x20; ? ? //輸出高
}
void CMS1650_Start(void) //SCL 為“1”,SDA 從“1”跳“0”,認為是開始信號
{?
?? ?SDA_OUT();//設置/SCL、SDA?為輸出腳
?? ?SET_CMS_SCL;
?? ?SET_CMS_SDA;
?? ?delay_us(5);
?? ?CLS_CMS_SDA;
?? ?delay_us(5);
?? ?CLS_CMS_SCL;//鉗住I2C總線,準備發(fā)送或接收數(shù)據(jù),(IIC規(guī)定只有在SCL為低電平期間,數(shù)據(jù)線上才允許高低變化,所以開始信號啟動后,拉低SCL)
}
void CMS1650_Stop(void) // SCL 為“1”電平,SDA 從“0”跳“1”,認為是結束信號
{?
?? ?SDA_OUT();
?? ?SET_CMS_SCL;
?? ?CLS_CMS_SDA;
?? ?delay_us(5);
?? ?SET_CMS_SDA;
?? ?delay_us(5);//停止信號,就不用把SCL拉低
}
(2)應答信號
應答信號由接收設備產生,在SCL為高電平期間,接收設備將SDA拉低說明數(shù)據(jù)傳輸正確,產生應答。
所以我們代碼應該這樣寫,傳輸完數(shù)據(jù)后,得先釋放數(shù)據(jù)線;再將SCL拉高,判斷低電平是否到來。
//等待從機應答信號到來
//返回值:1,接收應答失敗
//? ? ? ? ? ? ? 0,接收應答成功
u8 CMS1650_Wait_Ack(void)
{
?? ?u16?time = 0;
??? ?SDA_INT();//將SDA設置為上拉輸入 ,主機釋放數(shù)據(jù)總線(總線在空閑狀態(tài)為高電平)等待從機產生應答信號?? ? ??
? ? delay_us(5);??
?? ?SET_CMS_SCL;//? ?SCL拉高
?? ?while(SDA == 1)//在while循環(huán)延時這段時間內,看叢機是否有產生應答信號,有的話SDA就=0,跳出循環(huán)
?? ?{
?? ??? ?time++;
?? ??? ?if(time>255)//從機沒應答,傳輸失敗
?? ??? ?{
?? ??? ??? ?CMS1650_Stop();
?? ??? ??? ?return 1; //有必要的話顯示或者產生個中斷說明傳輸失敗,跳出循環(huán)。注:return可以可以跳出while循環(huán)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue:不跳出當前循環(huán),結束本次循環(huán)(結束當前循環(huán)),執(zhí)行下一輪循環(huán)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break:跳出當前循環(huán),結束該循環(huán)執(zhí)行
?? ??? ?}
?? ?}
?? ?CLS_CMS_SCL;
?? ?return 0; ?
}
(3)寫入數(shù)據(jù)
void CMS1650_SendByte(u8 txd)
{
? u8 t = 0; ??
//?? SDA_OUT();
// ?CLS_CMS_SCL;//拉低時鐘開始數(shù)據(jù)傳輸?? ?,開始信號已經(jīng)拉低SCL了,這里可以不用寫了
? ?for(t=0;t<8;t++)
? ?{ ??
?? ??? ??? ?if((txd&0x80)>>7)
?? ??? ??? ??? ?SET_CMS_SDA;
?? ??? ??? ?else
?? ??? ??? ??? ?CLS_CMS_SDA;
?? ??? ??? ?txd<<=1;?
?? ??? ??? ?delay_us(5);?
?? ??? ??? ?SET_CMS_SCL;//數(shù)據(jù)發(fā)送完,拉高時鐘
?? ??? ??? ?delay_us(5);?
? ? ? ? ? ? CLS_CMS_SCL;//拉低時鐘開始數(shù)據(jù)傳輸?? ?
?? ??? ??? ?delay_us(5);
?? ? }
}
對于數(shù)據(jù)的寫入為啥要SCL 從“0”跳到“1”,再從“1”跳到“0”這么寫,我們來看看接收方是怎么接收就一目了然了;
從設備收數(shù)據(jù):主設備發(fā)送了開始位后,把clk拉低,只有clk拉低,sda才可以做高低變化; 當clk被拉高時,(0->1)從設備就會去讀取sda的高低電平值;clk再次被拉低時,(1->0)從設備認為此位已讀取完畢,認為是有效位,等待clk再次拉高,讀取下一位。
(4)一個完整的寫顯示時序
首先得先寫入數(shù)據(jù)命令,然后開顯示確定顯示的亮度
8段顯示的話就是小數(shù)點也顯示出來
再來確定顯存地址(確定位選地址)
最后
void main()
{
? u8 t = 0;
?? ?LED_Init(); //SCL SDA?設置為輸出
? ?delay_ms(300);?? ?//延時一段時間,否則開顯示無響應
? ?CMS1650_SendByte(0x48);
? ?CMS1650_Wait_Ack();//等待應答
?//這里應答處理,看大家要做什么處理,這里應答處理我就先不作處理
?? CMS1650_SendByte(0x30);//開顯示:3級亮度
?? ?CMS1650_Wait_Ack();//等待應答?? ?
?? ?CMS1650_Stop();
?? ?CMS1650_WriteByte(0x6E,0x7f);
?? ?CMS1650_WriteByte(0x6C,0x7f);
?? ?CMS1650_WriteByte(0x6A,0x7f);
?? ?CMS1650_WriteByte(0x68,0x7f);//開機8888
?//單片機上電數(shù)碼管顯示8.8.8.8.
}
全部代碼
void LED_Init(void)
{
? P0TRIS |= 0x10; //設置P04輸出 SCL
?? ?P0 |= 0x10; ? ? //輸出高?? ?
?
?? ?P0TRIS |= 0x20; //設置P05輸出 SDA
?? ?P0 |= 0x20; ? ? //輸出高
}
void CMS1650_Start(void) //SCL 為“1”,SDA 從“1”跳“0”,認為是開始信號
{?
?? ?SDA_OUT();
?? ?SET_CMS_SCL;
?? ?SET_CMS_SDA;
?? ?delay_us(5);
?? ?CLS_CMS_SDA;
?? ?delay_us(5);
?? ?CLS_CMS_SCL;//鉗住I2C總線,準備發(fā)送或接收數(shù)據(jù)
}
void CMS1650_Stop(void) // SCL 為“1”電平,SDA 從“0”跳“1”,認為是結束信號
{?
?? ?SDA_OUT();
?? ?SET_CMS_SCL;
?? ?CLS_CMS_SDA;
?? ?delay_us(5);
?? ?SET_CMS_SDA;
?? ?delay_us(5);
}
//等待從機應答信號到來
//返回值:1,接收應答失敗
// ? ? ? ?0,接收應答成功
u8 CMS1650_Wait_Ack(void)
{
?? ?u16 time = 0;
?? ?SDA_OUT();
?? ?SET_CMS_SDA;delay_us(1);//主機釋放數(shù)據(jù)總線,(總線在空閑狀態(tài)為高電平)等待從機產生應答信號?? ? ??
?? ?SET_CMS_SCL;delay_us(1);?? ??
?? ?SDA_INT();//將SDA設置為上拉輸入
?? ?while(SDA == 1)//在while循環(huán)延時這段時間內,看叢機是否有產生應答信號,有的話SDA就=0,跳出循環(huán)
?? ?{
?? ??? ?time++;
?? ??? ?if(time>255)//從機沒應答,傳輸失敗
?? ??? ?{
?? ??? ??? ?CMS1650_Stop();
?? ??? ??? ?return 1; //有必要的話顯示或者產生個中斷說明傳輸失敗
?? ??? ?}
?? ?}
?? ?CLS_CMS_SCL;
?? ?return 0; ?
}
void CMS1650_SendByte(u8 txd)
{
? u8 t = 0; ??
//?? ?SDA_OUT();
// ?CLS_CMS_SCL;//拉低時鐘開始數(shù)據(jù)傳輸?? ?,開始信號已經(jīng)拉低SCL了,這里可以不用寫了
? ?for(t=0;t<8;t++)
? ?{ ??
?? ??? ??? ?if((txd&0x80)>>7)
?? ??? ??? ??? ?SET_CMS_SDA;
?? ??? ??? ?else
?? ??? ??? ??? ?CLS_CMS_SDA;
?? ??? ??? ?txd<<=1;?
?? ??? ??? ?delay_us(5);?
?? ??? ??? ?SET_CMS_SCL;//數(shù)據(jù)發(fā)送完,拉高時鐘
?? ??? ??? ?delay_us(5);?
? ? ? ? ? ?CLS_CMS_SCL;//拉低時鐘開始數(shù)據(jù)傳輸?? ?
?? ??? ??? ?delay_us(5);
?? ? }
}
void CMS1650_WriteByte(u8 Addr,u8 Data)
{
?? ?CMS1650_Start();
?? ?CMS1650_SendByte(Addr);
?? ?CMS1650_Wait_Ack();//等待應答
?? ?CMS1650_SendByte(Data);
?? ?CMS1650_Wait_Ack();//等待應答?? ?
?? ?CMS1650_Stop();
}
總結
- 上一篇: 人在旅途——》云南8天出行日程清单
- 下一篇: 计算机数据采集原理是什么,数据采集器工作