最近从stm32f1转用stm32f4,发现时钟和IO有很大的改变。为了快速上手F4打算把F1板子的OLEDIIC移植作为练习。关于OLED,IIC的讲解,网上有很多,我就不多阐述了,我想直接通过代码来展示我移植的过程。
首先是查询正点原子F4资料种的引脚分配表,确定IIC需要使用的IO口,SCL--PB8,SDA--PB9
然后开始写myiic的代码(GPIO的设置,根据IIC时序图写IIC的开始,结束,响应.....代码)
#include "myiic.h"
#include "delay.h"
//IIC的初始化
//SDA PB9
//SCL PB8
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//GPIOB10,B11³õʼ»¯ÉèÖÃ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 |GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
IIC_SCL=1;
IIC_SDA=1;
}
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(2);
IIC_SDA=0;
delay_us(2);
IIC_SCL=0; //钳住I2C,准备接受或者发送数据
}
void IIC_Stop(void)
{
SDA_OUT();//sdaÏßÊä³ö
IIC_SCL=0;
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
IIC_SDA=1;
delay_us(2);
}
//返回值:1:成功 0:失败
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN();
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
delay_us(4);
IIC_SCL=0;
}
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(4);
IIC_SCL=1;
delay_us(4);
IIC_SCL=0;
}
u8 test=0;
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(5);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
delay_us(5);
}
}
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(5);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(5);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
附上头文件:
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
//这两句的意思分别是:PB9的输入/输出模式
#define SDA_IN() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;}
#define IIC_SCL PBout(8) //SCL
#define IIC_SDA PBout(9) //SDA
#define READ_SDA PBin(9) //输出SDA
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(u8 txd);
u8 IIC_Read_Byte(unsigned char ack);
u8 IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
然后开始移植OLED的代码:(这一段没有任何需要改动的地方,直接大胆的搬)
#include "oled.h"
#include "codetab.h"//这是字库,可以网上找
#include "delay.h"
#include "myiic.h"
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(IIC_Byte & 0x80)
IIC_SDA=1;
else
IIC_SDA=0;
IIC_SCL=high;
delay_us(4);
IIC_SCL=0;
IIC_Byte<<=1;
}
IIC_SDA = 1;
IIC_SCL=1;
delay_us(4);
IIC_SCL=0;
}
void OLED_WrDat(unsigned char IIC_Data)
{
IIC_Start();
IIC_Send_Byte(0x78);
IIC_Wait_Ack();
IIC_Send_Byte(0x40); //write data
IIC_Wait_Ack();
IIC_Send_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
}
void OLED_WrCmd(unsigned char IIC_Command)
{
IIC_Start();
IIC_Send_Byte(0x78); //Slave address,SA0=0
if(IIC_Wait_Ack())
{
while(1);
}
IIC_Send_Byte(0x00); //write command
IIC_Wait_Ack();
IIC_Send_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(((x&0xf0)>>4)|0x10);
OLED_WrCmd((x&0x0f)|0x01);
}
void OLED_Fill(unsigned char bmp_dat)
{
unsigned char y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(bmp_dat);
}
}
void OLED_CLS(void)
{
unsigned char y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(0);
}
}
void OLED_Init(void)
{
delay_ms(500);
OLED_WrCmd(0xae);//--turn off oled panel
OLED_WrCmd(0x00);//---set low column address
OLED_WrCmd(0x10);//---set high column address
OLED_WrCmd(0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WrCmd(0x81);//--set contrast control register
OLED_WrCmd(Brightness); // Set SEG Output Current Brightness
OLED_WrCmd(0xa1);//--Set SEG/Column Mapping
OLED_WrCmd(0xc8);//Set COM/Row Scan Direction
OLED_WrCmd(0xa6);//-