“大圣小车”——STM32F103驱动OLED I2C硬件方式程序改造说明

STM32F103驱动OLED I2C硬件方式程序改造

研究小车自带的OLED I2C程序,I2C是用GPIO软件模拟出来的,查阅STM32F103 芯片有I2C通信功能,于是,对原驱动程序进行适当修改,改为I2C硬件方式驱动。查阅相关资料,主要参考了“STM32F103C8T6引脚定义” 、“STM32F103xx固件函数库用户手册”、网文“【STM32F103笔记】9、I2C通信——玩转OLED(OLED命令详解)” 详见:http://t.csdnimg.cn/jUvkR

修改函数 void OLED_I2C_Init(void)

原函数

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(x))

/*引脚初始化*/
void OLED_I2C_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

修改后程序

**注意:**I2C2InitStruct.I2C_ClockSpeed = 150000;//设置时钟频率,这个值不能高于 400KHz 这个值太高,OLED_ShowBinNum函数显示不正常,我的实验板是这样!!!

/*引脚初始化*/
void OLED_I2C_Init(void)
{
  GPIO_InitTypeDef PB1011InitStruct;
	I2C_InitTypeDef I2C2InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	
	PB1011InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	PB1011InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	PB1011InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PB1011InitStruct);
	
	I2C2InitStruct.I2C_Mode = I2C_Mode_I2C; //设置 I2C 为 I2C 模式
	I2C2InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; //I2C 快速模式 Tlow / Thigh = 2 (时钟工作频率高于 100KHz)下才有意义
	I2C2InitStruct.I2C_Ack = I2C_Ack_Enable; // 使能应答(ACK)
	I2C2InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设置第一个设备自身地址为 7 位地址
	I2C2InitStruct.I2C_ClockSpeed = 150000;//设置时钟频率,这个值不能高于 400KHz  这个值太高,OLED_ShowBinNum函数显示不正常
	I2C_Init(I2C2, &I2C2InitStruct); //I2C初始化
	I2C_Cmd(I2C2, ENABLE); //使能 I2C 外设
}

修改void OLED_I2C_Start(void)

原程序

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void OLED_I2C_Start(void)
{
	OLED_W_SDA(1);
	OLED_W_SCL(1);
	OLED_W_SDA(0);
	OLED_W_SCL(0);
}

修改后程序

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void OLED_I2C_Start(void)
{
// 发出Start信号并检测EV5
	I2C_GenerateSTART(I2C2, ENABLE);
	while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
}

修改void OLED_I2C_Stop(void)

原程序

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void OLED_I2C_Stop(void)
{
	OLED_W_SDA(0);
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

修改后程序

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void OLED_I2C_Stop(void)
{
// 发送Stop信号
	I2C_GenerateSTOP(I2C2, ENABLE);
}

修改 void OLED_I2C_SendByte(uint8_t Byte)

原程序

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i++)
	{
		OLED_W_SDA(Byte & (0x80 >> i));
		OLED_W_SCL(1);
		OLED_W_SCL(0);
	}
	OLED_W_SCL(1);	//额外的一个时钟,不处理应答信号
	OLED_W_SCL(0);
}

修改后程序

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
// 发送数据(寄存器地址或命令,一般来说,向I2C通信对应的设备发送数据,是对其某个寄存器发送数据,或者发送对应的命令及数据),并检测EV8
	I2C_SendData(I2C2, Byte);
	while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

新增函数 void OLED_I2C_Send7bitAddress(uint8_t slave_addr)

该函数用来发送从机地址

/**
  * @brief  I2C发送7位地址
  * @param  slave_addr 要发送的7位地址
  * @retval 无
  */
void OLED_I2C_Send7bitAddress(uint8_t slave_addr)
{
// 发送地址并检测EV6
	I2C_Send7bitAddress(I2C2, slave_addr, I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}

修改void OLED_WriteCommand(uint8_t Command)

原程序

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x00);		//写命令
	OLED_I2C_SendByte(Command); 
	OLED_I2C_Stop();
}

修改后程序

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
	OLED_I2C_Start();
	OLED_I2C_Send7bitAddress(0x78);		//从机地址
	OLED_I2C_SendByte(0x00);		//写命令
	OLED_I2C_SendByte(Command); 
	OLED_I2C_Stop();
}

修改void OLED_WriteData(uint8_t Data)

原程序

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x40);		//写数据
	OLED_I2C_SendByte(Data);
	OLED_I2C_Stop();
}

修改后程序

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
	OLED_I2C_Start();
	OLED_I2C_Send7bitAddress(0x78);		//从机地址
	OLED_I2C_SendByte(0x40);		//写数据
	OLED_I2C_SendByte(Data);
	OLED_I2C_Stop();
}

其他程序没有改动。

在主程序中进行程序测试:

int main(void)
{
	OLED_Init();
	OLED_ShowChar(1,1,'F');
	OLED_ShowString(1,3,"XG nihao!");
	OLED_ShowNum(2,1,1000,4);
	OLED_ShowSignedNum(2,7,-991,3);
	OLED_ShowHexNum(3,1,0xff01,4);
	OLED_ShowBinNum(4,1,0xff01,16);
	while (1)
	{
		
	}
}

显示图片 通信速度:150000
在这里插入图片描述显示图片 通信速度:200000
在这里插入图片描述

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值