一、I2C
I2C時序:時鐘線SCL高電平下:SDA由高變低代表啟動信號,開始發送數據;SCL高電平時,數據穩定,數據可以被讀走,開始進行讀操作,SCL低電平時,數據發生改變;每發送一個字節的數據都會產生應答信號;時鐘線SCL低電平下:SDA由低變高代表傳輸數據結束
初始化: P6數據線(SDA) P7時鐘線(SCL),選用P6和P7兩根引腳,并給他們置為低電平
分別輸出數據線和時鐘線
開始信號:在空閑狀態下先將時鐘線置為低電平輸出0,數據線置位高電平,再根據開始信號的觸發條件:SCL高電平時,SDA由高變低,最后再拉低SCL(增加可靠性和準確行)
停止信號:SDA由低變高,原理同開始信號大差不差
ACK應答信號,假應答
發送一個字節
發送一個字節,時鐘線拉低時,發送數據;拉高讀取數據
void i2c_Send_Byte(char data)
{int i=0;for(i=7;i>=0;i--)//循環發送8位數據{i2c_SCL(0);//時鐘線拉低i2c_SDA(data &(0x1<<i));//發送數據i2c_SCL(1);//時鐘線拉高,讓接受方接收數據i2c_SCL(0);//時鐘線拉低}
}
發送多個字節
void i2c_Send_Bytes(int *p,int len)
{int i,j;for(j=0;j<len;j++){for(i=7;i>=0;i--){i2c_SCL(0);//時鐘線拉低i2c_SDA(p[j] &(0x1<<i));i2c_SCL(1);//時鐘線拉高,讓接受方接收數據i2c_SCL(0);//時鐘線拉低}i2c_Ack();//一個字節寫完過后需要有應答信號}
}
二、oled
數據格式
在執行到Control Byte,寫命令或者寫數據是根據D\C(為0時命令,1時數據),根據數據格式寫
oled的初始化需要用到IIC(引腳的配置),隨后先將oled關閉,最后再打開,中間根據數據手冊而寫
清空函數:防止有外部因素的影響
void Oled_clear(void)
{int page;//頁int seg;//列for(page=0;page<8;page++)//按頁遍歷{for(seg=0;seg<128;seg++)//每一頁的每一列{Oled_Write_cmd(0xB0+page);//頁地址Oled_Write_cmd(0x00+(seg & 0xf));//設置seg列的低地址Oled_Write_cmd(0x10+((seg>>4)&0xf));//設置seg列的高地址Oled_Write_data(0x0);//清屏}}
}
每一頁有8行
設置行
低位與高位
顯示數據:32列需要使用4頁,32-64防止數據的覆蓋
unsigned char buff[8][32]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0x3C,0x18,0x08,0x00,0x00,0x00,0x00,0xFC,0xF8,0x08,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0x60,0x40,0x00,0x00,0x00,0x00},
{0x00,0x00,0x20,0x10,0x08,0x04,0x03,0xFF,0xFF,0x01,0x00,0x40,0x40,0x20,0x20,0x10,0xFF,0xFF,0x08,0x0C,0x06,0x02,0x03,0x01,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00},
{0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x4F,0x47,0x40,0x40,0x40,0x40,0x40,0x40,0xFC,0xFC,0x43,0x43,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x63,0x63,0x41,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00,0x08,0x10,0x70,0xE0,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFC,0xFC,0x48,0x40,0x40,0x40,0x40,0x40,0x60,0x60,0x40,0x00,0x00,0x00},
{0x00,0x04,0x0C,0x18,0x78,0x30,0x00,0x80,0x78,0x24,0x20,0x20,0xA2,0x22,0x22,0x22,0x22,0x22,0x3F,0x3F,0x22,0x22,0x22,0x22,0x23,0xA3,0x22,0x30,0x30,0x20,0x00,0x00},
{0x00,0x40,0x40,0xC0,0xC0,0xE0,0x7C,0x03,0x00,0x00,0x00,0x00,0xFF,0xFF,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x30,0x70,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00}};void Oled_Display(void)
{int page;//頁int seg;//列for(page=0;page<4;page++)//按頁遍歷{for(seg=0;seg<32;seg++)//每一頁的每一列{Oled_Write_cmd(0xB0+page);//頁地址Oled_Write_cmd(0x00+(seg & 0xf));//設置seg列的低地址Oled_Write_cmd(0x10+((seg>>4)&0xf));//設置seg列的高地址Oled_Write_data(buff[page][seg]);//顯示數據}}for(page=0;page<4;page++)//按頁遍歷{for(seg=32;seg<64;seg++)//每一頁的每一列{Oled_Write_cmd(0xB0+page);//頁地址Oled_Write_cmd(0x00+(seg & 0xf));//設置seg列的低地址Oled_Write_cmd(0x10+((seg>>4)&0xf));//設置seg列的高地址Oled_Write_data(buff[page+4][seg-32]);//顯示數據//當seg從 32 開始計數時,通過seg - 32可以將其轉換為從 0 開始的索引,//這樣就能正確地從buff數組中獲取與當前 OLED 頁面內列位置相對應的數據}}
}