1. 程式人生 > >stm32 IIC oled 介紹

stm32 IIC oled 介紹

IIC 簡介

IIC oled 介紹找另一篇文章,這裡主要有IIC,和如何編寫oled.c程式碼 IIC(Inter-Integrated Circuit)匯流排是一種由 PHILIPS 公司開發的兩線式 匯流排, 用於連線微控制器及其外圍裝置。它是由資料線 SDA 和時鐘 SCL 構成的序列匯流排, 可傳送和接收資料。

在 CPU 與被控 IC 之間、IC 與 IC 之間進行雙向傳送,高速 IIC 匯流排一般可達 400kbps 以上。 I2C 匯流排在傳送資料過程中共有三種類型訊號, 它們分別是:開始訊號、結束訊號和應答訊號。

開始訊號:SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送資料。 結束訊號:SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送資料。 應答訊號:接收資料的 IC 在接收到 8bit 資料後,向傳送資料的 IC 發出特定 的低電平脈 衝,表示已收到資料。CPU 向受控單元發出一個訊號後,等待受控單元發出一個應答訊號,CPU 接收到應答訊號後,根據實際情況作出是否繼續傳遞訊號的判斷。若未收到應答訊號,由判斷為 受控單元出現故障。 這些訊號中,起始訊號是必需的,結束訊號和應答訊號,都可以不要

軟體設計

  • IIC設定
void I2C_Configuration(void)
{
	I2C_InitTypeDef  I2C_InitStructure;
	GPIO_InitTypeDef  GPIO_InitStructure; 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

	/*STM32F103C8T6晶片的硬體I2C: PB6 -- SCL; PB7 -- SDA */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_OD;//I2C必須開漏輸出
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	I2C_DeInit(I2C1);//使用I2C1
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主機的I2C地址,隨便寫的
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

	I2C_Cmd(I2C1, ENABLE);
	I2C_Init(I2C1, &I2C_InitStructure);
}
  • IIC傳送資料
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//開啟I2C1
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

	I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 預設0x78
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1, addr);//暫存器地址
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_SendData(I2C1, data);//傳送資料
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTOP(I2C1, ENABLE);//關閉I2C1匯流排
}

oled的寫命令和資料

void WriteCmd(unsigned char I2C_Command)//寫命令
{
	I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)//寫資料
{
	I2C_WriteByte(0x40, I2C_Data);
}

OLEd初始化


void OLED_Init(void)
{
	delay_ms(100); //這裡的延時很重要
	
	WriteCmd(0xAE); //開顯示
	WriteCmd(0x20);	//設定記憶體定址模式	
	WriteCmd(0x10);	//00,水平定址模式;01,垂直定址模式;10,頁面定址模式(重置);11,無效
	WriteCmd(0xb0);	//為頁面定址模式設定頁面開始地址,0-7
	WriteCmd(0xc8);	//設定COM輸出掃描方向
	WriteCmd(0x00); //---設定低列地址
	WriteCmd(0x10); //---設定高列地址
	WriteCmd(0x40); //--設定起始行地址
	WriteCmd(0x81); //--set contrast control register
	WriteCmd(0xff); //亮度調節 0x00~0xff
	WriteCmd(0xa1); //--設定段重新對映0到127
	WriteCmd(0xa6); //--設定正常顯示
	WriteCmd(0xa8); //--設定複用比(1 ~ 64)
	WriteCmd(0x3F); //
	WriteCmd(0xa4); //0xa4,輸出遵循RAM內容;0xa5,Output忽略RAM內容
	WriteCmd(0xd3); //-設定顯示抵消
	WriteCmd(0x00); //-not offset
	WriteCmd(0xd5); //--設定顯示時鐘分頻/振盪器頻率
	WriteCmd(0xf0); //--設定分率
	WriteCmd(0xd9); //--設定pre-charge時期
	WriteCmd(0x22); //
	WriteCmd(0xda); //--設定com大頭針硬體配置
	WriteCmd(0x12);
	WriteCmd(0xdb); //--設定vcomh
	WriteCmd(0x20); //0x20,0.77xVcc
	WriteCmd(0x8d); //--設定DC-DC
	WriteCmd(0x14); //
	WriteCmd(0xaf); //--開啟oled面板
}

設定起始點座標

void OLED_SetPos(unsigned char x, unsigned char y) //設定起始點座標
{ 
	WriteCmd(0xb0+y);
	WriteCmd(((x&0xf0)>>4)|0x10);
	WriteCmd((x&0x0f)|0x01);
}

全屏填充

void OLED_Fill(unsigned char fill_Data)//全屏填充
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		WriteCmd(0xb0+m);		//page0-page1
		WriteCmd(0x00);		//low column start address
		WriteCmd(0x10);		//high column start address
		for(n=0;n<128;n++)
			{
				WriteDat(fill_Data);
			}
	}
}

清屏

void OLED_CLS(void)//清屏
{
	OLED_Fill(0x00);
}

將OLED從休眠中喚醒

//--------------------------------------------------------------
void OLED_ON(void)
{
	WriteCmd(0X8D);  //設定電荷泵
	WriteCmd(0X14);  //開啟電荷泵
	WriteCmd(0XAF);  //OLED喚醒
}

讓OLED休眠 – 休眠模式下,OLED功耗不到10uA

//--------------------------------------------------------------
void OLED_OFF(void)
{
	WriteCmd(0X8D);  //設定電荷泵
	WriteCmd(0X10);  //關閉電荷泵 
	WriteCmd(0XAE);  //OLED休眠
}

顯示codetab.h中的ASCII字元,有68和816可選擇

/

/--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<6;i++)
					WriteDat(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i]);
				OLED_SetPos(x,y+1);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}

//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          : 
// Parameters     : x,y -- 起始點座標(x:0~127, y:0~7); N:漢字在codetab.h中的索引
// Description    : 顯示codetab.h中的漢字,16*16點陣
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_SetPos(x , y);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	OLED_SetPos(x,y + 1);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}

//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls          : 
// Parameters     : x0,y0 -- 起始點座標(x0:0~127, y0:0~7); x1,y1 -- 起點對角線(結束點)的座標(x1:1~128,y1:1~8)
// Description    : 顯示BMP點陣圖
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	unsigned int j=0;
	unsigned char x,y;

  if(y1%8==0)
		y = y1/8;
  else
		y = y1/8 + 1;
	for(y=y0;y<y1;y++)
	{
		OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
		{
			WriteDat(BMP[j++]);
		}
	}
}