0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

AT89S52單片機(jī)入門

科技綠洲 ? 來源:gaoyang9992006 ? 作者:gaoyang9992006 ? 2023-09-11 10:03 ? 次閱讀

最近撿到一個十幾年前學(xué)單片機(jī)時候的入門單片機(jī):AT89S52。

我覺得我應(yīng)該做點什么,于是便去翻騰垃圾,又撿到一片DS1302;再從一個玩具上拆下一個32.768KHZ晶振,找到一片0.91寸I2C接口OLED,還有一個ADC,TLC2543,DS12887……然后就去嘉立創(chuàng)“薅羊毛”打了一個板子開始玩起來

3D效果圖:

圖片

實物圖:

圖片

以前做什么都是本著能用就好的拿來主義,很少去深度思考人家是怎么寫的。比如這個OLED模塊,大部分都是用廠家提供的那一套,沒有思考是怎么寫的,底層是怎么實現(xiàn)的,也就是不重復(fù)造輪子。

然而我今天閑了,想要看看輪子怎么造的,最后也要仿造人家的輪子做個零件出來

1、I2C的基礎(chǔ)操作函數(shù)

首先,看了一下廠家提供的示例,比如51單片機(jī)用IO模擬I2C的基礎(chǔ)函數(shù)有:起始信號、結(jié)束信號、等待信號響應(yīng)。

//起始信號
void I2C_Start(void)
{
OLED_SDA_Set();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Clr();
IIC_delay();
OLED_SCL_Clr();


}


//結(jié)束信號
void I2C_Stop(void)
{
OLED_SDA_Clr();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Set();
}


//等待信號響應(yīng)
void I2C_WaitAck(void) //測數(shù)據(jù)信號的電平
{
OLED_SDA_Set();
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}

2、I2C的字節(jié)寫入函數(shù):寫入一個字節(jié)

//寫入一個字節(jié)
void Send_Byte(u8 dat)
{
u8 i;
for(i=0;i< 8;i++)
{
OLED_SCL_Clr();//將時鐘信號設(shè)置為低電平
if(dat&0x80)//將dat的8位從最高位依次寫入
{
OLED_SDA_Set();
}
else
{
OLED_SDA_Clr();
}
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
dat< <=1;
}
}

3、給OLED寫入指令或數(shù)據(jù)

接下來,在以上的基礎(chǔ)函數(shù)前提下可以操作OLED了,通過以上的組合可以實現(xiàn)給OLED寫入指令或數(shù)據(jù)。

//發(fā)送一個字節(jié)
//向SSD1306寫入一個字節(jié)。
//mode:數(shù)據(jù)/命令標(biāo)志 0,表示命令;1,表示數(shù)據(jù);
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if(mode){Send_Byte(0x40);}
else{Send_Byte(0x00);}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}

4、利用基礎(chǔ)的寫入操作可以實現(xiàn)上層次的傳送各種指令和數(shù)據(jù)給OLED的控制器SSD1306了

/*
坐標(biāo)設(shè)置,對于128*32分辨率的OLED:x從127;y從0到3
*/


void OLED_Set_Pos(u8 x, u8 y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0) > >4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f),OLED_CMD);
}
//開啟OLED顯示
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//關(guān)閉OLED顯示
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
//清屏函數(shù),清完屏,整個屏幕是黑色的!和沒點亮一樣!!!
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i< 4;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //設(shè)置頁地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //設(shè)置顯示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //設(shè)置顯示位置—列高地址
for(n=0;n< 128;n++)OLED_WR_Byte(0,OLED_DATA);
} //更新顯示
}






//初始化
void OLED_Init(void)
{


OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
OLED_WR_Byte(0x00,OLED_CMD); /*set lower column address*/
OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/
OLED_WR_Byte(0x00,OLED_CMD); /*set display start line*/
OLED_WR_Byte(0xB0,OLED_CMD); /*set page address*/
OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
OLED_WR_Byte(0xff,OLED_CMD); /*128*/
OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap*/
OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
OLED_WR_Byte(0x1F,OLED_CMD); /*duty = 1/32*/
OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/
OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
OLED_WR_Byte(0x00,OLED_CMD);
OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
OLED_WR_Byte(0x80,OLED_CMD);
OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
OLED_WR_Byte(0x1f,OLED_CMD);
OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
OLED_WR_Byte(0x00,OLED_CMD);
OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
OLED_WR_Byte(0x40,OLED_CMD);
OLED_WR_Byte(0x8d,OLED_CMD); /*set charge pump enable*/
OLED_WR_Byte(0x14,OLED_CMD);
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}

5、研究一下傳送進(jìn)去的數(shù)據(jù)是怎么對應(yīng)的顯示在128*32的點陣上的

圖片

如果上圖看不懂,就看下面的文字部分。

這個芯片最大支持12864,我手里用的0.91寸的只有12832,也就是只使用PAGE0~PAGE3。

屏幕的點陣橫向看作x,即x列,總數(shù)是128列,x∈[0,127];

屏幕的點陣豎向看作y,即y行,總數(shù)是032行,y∈[0,031];

而芯片寫入是按照頁寫入的,即y屬于PAGE0~PAGE3。

所以,這一點很重要。注意,下面這個廠家提供的操作函數(shù)種的y是對應(yīng)的頁的編號。

/*
坐標(biāo)設(shè)置,對于128*32分辨率的OLED:x從127;y從0到3
*/


void OLED_Set_Pos(u8 x, u8 y) ;

于是乎顯示一個1,我們要把1圖像的每一列的8BIT裝進(jìn)一個頁的數(shù)據(jù)里。如下圖所示:

圖片

這是6*8大小的點陣字符,如果從第一行寫,那么就是寫入第0頁,然后將對應(yīng)列的幾個字節(jié)按順序?qū)懭爰纯伞?/p>

例如我寫入左下角,那么對應(yīng)的就是PAGE3,然后x坐標(biāo)對應(yīng)0,1,2,3,4,5。

OLED_Set_Pos(0,3);
OLED_WR_Byte(0x00,OLED_DATA);
OLED_Set_Pos(1,3);
OLED_WR_Byte(0x00,OLED_DATA);
OLED_Set_Pos(2,3);
OLED_WR_Byte(0x42,OLED_DATA);
OLED_Set_Pos(3,3);
OLED_WR_Byte(0x7F,OLED_DATA);
OLED_Set_Pos(4,3);
OLED_WR_Byte(0x40,OLED_DATA);
OLED_Set_Pos(5,3);
OLED_WR_Byte(0x00,OLED_DATA);

顯示效果:

圖片

所以,明白了這一點就可以實現(xiàn)各種自定義的圖像了。另外,也可以使用相關(guān)的生成工具生成相關(guān)的圖像編碼。

比如我們繪制一個電池的圖標(biāo):

圖片

將11個字節(jié)數(shù)據(jù)放到一個數(shù)組,這樣我們可以用循環(huán)調(diào)用。

unsigned char temp[11]={0x42,0xFF,0x81,0xBD,0xBD,0xBD,0xBD,0xBD,0x81,0xFF,0x18};

考慮到剛才顯示1的那個位置有鼓包,我們將其向右偏移20個像素點放置,同樣放在第三頁顯示。

for(i=0;i< 11;i++)
{
OLED_Set_Pos(i+20,3);
OLED_WR_Byte(temp[i],OLED_DATA);
}
delay_ms(2000);

顯示效果如下圖所示,怎么樣,是不是很贊?現(xiàn)在你是不是學(xué)會顯示任何圖案了?

圖片

接下來,我們造一個函數(shù)實現(xiàn)一個點的顯示,參數(shù)為p(x,y)的絕對坐標(biāo)。

/*
x:0~127;y:0~31
*/


void setPixel(int x, int y)
{
unsigned char page;
unsigned char bits;
page = y / 8;
bits = y % 8;
OLED_Set_Pos(x,page);
OLED_WR_Byte(1<

利用這個函數(shù),我們可以繪制正弦曲線了。

接下來,測試51使用math.h庫函數(shù)計算正弦波圖像,用于顯示正弦波。先直接輸出一個,然后翻轉(zhuǎn)一個顯示。

//正弦波
for(i=0;i< 128;i++)
{
y=16.0+sin(i*3.1415926/32.0)*16.0;
j=(unsigned int)(y);
setPixel(i,j);


}
OLED_Clear();
//正弦波
for(i=0;i< 128;i++)
{
y=16.0-sin(i*3.1415926/32.0)*16.0;
j=(unsigned int)(y);
setPixel(i,j);


}
OLED_Clear();

請注意上面的函數(shù),因為計算過程,正弦函數(shù)出來的都是0到1之間的小數(shù),所以要用浮點型,即y為浮點型變量。參與計算的常數(shù)也要寫作浮點型,免得給優(yōu)化掉,這樣就只能出來一條線了。

同樣,如果更改周期參數(shù),即可實現(xiàn)不同周期的正弦波顯示。

for(k=8;k<=64;k=k*2)
{
for(i=0;i< 128;i++)
{
y=16.0-sin(i*3.1415926/(float)k)*16.0;
j=(unsigned int)(y);
setPixel(i,j);
}
OLED_Clear();
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6030

    文章

    44489

    瀏覽量

    631980
  • AT89S52
    +關(guān)注

    關(guān)注

    9

    文章

    358

    瀏覽量

    87748
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4277

    瀏覽量

    62323
  • oled模塊
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    2813
收藏 人收藏

    評論

    相關(guān)推薦

    單片機(jī)很簡單,有點電子底子的都可以玩會

    、又可以動手DIY硬件,激發(fā)思考,積累的經(jīng)驗更多。誤區(qū)4,以AT89S52單片機(jī)入門AT89S52的內(nèi)部資源很少,一般的東西都需要外部,而且最小系統(tǒng)必須接晶振和復(fù)位電路,很麻煩??墒?/div>
    發(fā)表于 08-18 15:16

    單片機(jī)很簡單,有點電子底子的都可以玩會

    建議采用面包板上做實驗學(xué)習(xí)單片機(jī),成本低、又可以動手DIY硬件,激發(fā)思考,積累的經(jīng)驗更多。誤區(qū)4,以AT89S52單片機(jī)入門AT89S52
    發(fā)表于 06-02 15:16

    【轉(zhuǎn)】單片機(jī)入門的方法與誤區(qū)

    面包板上做實驗學(xué)習(xí)單片機(jī),成本低、又可以動手DIY硬件,激發(fā)思考,積累的經(jīng)驗更多。誤區(qū)4以AT89S52單片機(jī)入門AT89S52的內(nèi)部資源
    發(fā)表于 06-21 20:33

    AT89S52單片機(jī)的基本特征有哪些

    AT89S52單片機(jī)的內(nèi)部結(jié)構(gòu)是由哪些部分組成的?AT89S52單片機(jī)的基本特征有哪些?
    發(fā)表于 10-21 08:52

    AT89S52與RS-232的接口電路

    AT89S52與RS-232的接口電路 圖5 AT89S52與RS-232的接口電路 單片機(jī)采用AT89S52
    發(fā)表于 03-07 09:37 ?3011次閱讀
    <b class='flag-5'>AT89S52</b>與RS-232的接口電路

    at89s52單片機(jī)引腳圖,at89s52引腳說明

    本文為您介紹at89s52單片機(jī)引腳圖及引腳說明,at89S52特點及其功能。at89S52,高性能的8位單片機(jī)。
    發(fā)表于 04-29 22:04 ?7.9w次閱讀
    <b class='flag-5'>at89s52</b><b class='flag-5'>單片機(jī)</b>引腳圖,<b class='flag-5'>at89s52</b>引腳說明

    單片機(jī)AT89S52實用教程

    本文提供的單片機(jī)AT89S52實用教程,希望對你的學(xué)習(xí)有所幫助!
    發(fā)表于 06-03 16:00 ?794次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>AT89S52</b>實用教程

    AT89S52單片機(jī)入門與提高

    發(fā)表于 06-02 21:22 ?190次下載

    AT89S52單片機(jī)結(jié)構(gòu)

    AT89S52單片機(jī)結(jié)構(gòu),簡單易學(xué),另有相關(guān)配套視頻教程,請百度云搜索嘿咻大包子
    發(fā)表于 05-11 15:26 ?3次下載

    AT89S52單片機(jī)數(shù)控直流電源原理圖程序

    AT89S52單片機(jī)數(shù)控直流電源原理圖程序
    發(fā)表于 05-11 16:54 ?0次下載

    AT89S52單片機(jī)實現(xiàn)數(shù)控直流電流源論文

    AT89S52單片機(jī)實現(xiàn)數(shù)控直流電流源論文
    發(fā)表于 05-11 16:55 ?0次下載

    畢業(yè)設(shè)計-基于AT89S52單片機(jī)的電子萬年歷設(shè)計

    畢業(yè)設(shè)計-基于AT89S52單片機(jī)的電子萬年歷設(shè)計
    發(fā)表于 11-03 14:06 ?84次下載

    單片機(jī)AT89S52介紹

    AT89S52單片機(jī)的引腳、IO口介紹
    發(fā)表于 03-05 14:39 ?93次下載

    單片機(jī)at89s52和其他單片機(jī)比有什么優(yōu)劣勢

    單片機(jī)at89s52是一種高性能低功耗的采用CMOS工藝制造的8位微控制器,它提供下列標(biāo)準(zhǔn)特征:8K字節(jié)的程序存儲器,256字節(jié)的RAM,32條I/O線,2個16位定時器/計數(shù)器, 一個5中斷源兩個
    的頭像 發(fā)表于 05-16 16:52 ?5.4w次閱讀

    AT89S52單片機(jī)思維導(dǎo)圖

    AT89S52單片機(jī)思維導(dǎo)圖
    發(fā)表于 11-10 18:46 ?72次下載
    <b class='flag-5'>AT89S52</b><b class='flag-5'>單片機(jī)</b>思維導(dǎo)圖