Cet article est le premier blog de l'auteur, le but de sa rédaction est de m'inciter à apprendre et à partager avec tout le monde. Veuillez indiquer s'il y a des inexactitudes dans l'article.
Cet article est principalement un résumé de l'utilisation des différents écrans OLED rencontrés par l'auteur dans le processus d'apprentissage du micro-ordinateur monopuce.
Il existe de nombreux programmes pour l'écran OLED piloté par SSD1306. Il existe deux manières principales de communiquer avec le microcontrôleur, l'une est la communication SPI et l'autre est la communication I2C. Chaque méthode de communication est divisée en communication matérielle et logicielle.
Il y a quelques explications, le matériel utilisé par le premier auteur est basé sur STM32F1. Deuxièmement, étant donné que les fonctions de lecteur des OLED sont similaires, cet article enregistre uniquement les méthodes d'initialisation des différents modes de conduite. Il est pratique pour nous de transplanter sur différentes plates-formes en fonction des programmes et des écrans OLED entre nos mains.
1. Communication SPI
1. SPI matériel
Être ajouté…
2. Logiciel SPI
#define SCLK_PIN GPIO_Pin_6
#define SDIN_PIN GPIO_Pin_7
#define RST_PIN GPIO_Pin_0
#define DC_PIN GPIO_Pin_1
#define CS_PIN GPIO_Pin_10
//引脚宏定义 可根据实际电路连接方式更改
void OLED_Init(void) //OLED初始化函数
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = SCLK_PIN| SDIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, SCLK_PIN| SDIN_PIN| CS_PIN);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = RST_PIN |DC_PIN| CS_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,RST_PIN| DC_PIN| CS_PIN );
}
Ensuite, vous devez créer une fonction
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 i;
OLED_DC=cmd;
OLED_CS=0;
for(i=0;i<8;i++)
{
OLED_SCL=0;
if(dat&0x80)
OLED_SDA=1;
else
OLED_SDA=0;
OLED_SCL=1;
dat<<=1;
}
OLED_CS=1;
OLED_DC=1;
}
C'est la clé de notre communication avec l'appareil, et peut être écrite selon le chronogramme de la méthode de communication correspondante. Lorsque le paramètre cmd est 0, la fonction effectuera une opération de commande d'écriture, lorsque cmd vaut 1, la fonction effectuera une opération d'écriture de données.
Après cela, nous devons appeler cette fonction pour écrire une commande afin d'effectuer une série d'opérations d'initialisation sur le SSD1306. Cette étape peut également être écrite selon la fiche technique correspondante.
OLED_WR_Byte(0xAE,OLED_CMD);//--display off
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
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);//--set multiplex ratio(1to64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
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(0xD8,OLED_CMD);//set area color mode off
OLED_WR_Byte(0x05,OLED_CMD);//
OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//
OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
OLED_WR_Byte(0x30,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
OLED_WR_Byte(0x14,OLED_CMD);//
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
Deuxièmement, la communication I2C
1. Matériel I2C
Il y a plusieurs points à noter à propos de l'I2C matériel: le premier est que lors de la configuration du mode broche, il doit être configuré comme un mode de sortie à drain ouvert, et l'autre est que les fonctions de communication doivent appeler des fonctions de bibliothèque.
La routine de la famille des feux de forêt est la suivante:
void OLED_Init(void)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//硬件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;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(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;
I2C_Cmd(I2C1, ENABLE);
I2C_Init(I2C1, &I2C_InitStructure);
}
void OLED_WR_Byte(uint8_t data, uint8_t addr)
{
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总线
}
2. Logiciel I2C
#define SCL_PIN GPIO_Pin_6
#define SDA_PIN GPIO_Pin_7
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = SCL_PIN | SDA_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_SCL|GPIO_SDA);
}
De même, une fonction d'écriture de données peut être écrite selon le chronogramme du protocole de communication I2C.
void Write_IIC_Byte(unsigned char dat)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
OLED_SCLK_Clr();
for(i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{
OLED_SDIN_Set();}
else OLED_SDIN_Clr();
da=da<<1;
OLED_SCLK_Set();
OLED_SCLK_Clr();
}
}
void OLED_WR_Byte(u8 dat,u8 cmd)
{
OLED_SCLK_Set();
OLED_SDIN_Set();
OLED_SDIN_Clr();
OLED_SCLK_Clr(); //I2C_start
Write_IIC_Byte(0x78);
OLED_SCLK_Set();
OLED_SCLK_Clr(); //I2C_ack
if(cmd) Write_IIC_Byte(0x40);
else Write_IIC_Byte(0x00);
OLED_SCLK_Set();
OLED_SCLK_Clr(); //I2C_ack
Write_IIC_Byte(dat);
OLED_SCLK_Set();
OLED_SCLK_Clr(); //I2C_ack
OLED_SCLK_Set() ;
OLED_SDIN_Clr();
OLED_SDIN_Set(); //I2C_stop
}