@使用PIC单片机驱动OLED模块(软件模拟IIC模式)
使用PIC单片机驱动OLED模块(软件模拟IIC模式)
最近学习Microchhip的PIC18系列单片机,使用该款单片机进行一些外设的开发。发现网上的资料很少,故开了此个博客,对自己的学习过程进行一些记录,希望未来国内Microchip的社区能有更多的资源。
单片机型号
本次实验使用的单片机型号为PIC18F56Q71,Microchip公司提供了很多的开发板,但是没有进行过多的宣传,不像STM8或者51单片机那样热门。但是并不妨碍PIC单片机是一款非常好的单片机,在很多极端环境下都能正常的使用比如石油化工等方面。
OLED模块
OLED模块使用的是最常见的4引脚IIC驱动的OLED模块,淘宝价格大概十来块钱。对于STM系列和51单片机来说,各种资源随处可见,但是并没有适用于PIC单片机的资源。本文将对STM32F108C8T6的OLED驱动代码进行移植,使得PIC单片机能正常使用OLED模块。
开发环境
使用MPLAB X IDE进行开发,IDE版本为v6.20。代码生成器MCC版本为v5.5.1。这里注意:使用MCC版本为MCC Melody而不是MCC Classic。
实验开始
在做好各个前序工作后,就可以使用PIC单片机对OLED模块进行开发实验啦!
第一步打开XIDE,新建工程。
选择MCU型号以及下载器型号:
选择编译器:
两种方式打开MCC:
方式一:
方式二(tools->Embedded->MCC):
双击System中的Pins,就会得到两个窗口,这里选择RD4管脚以及RD5关键作为模拟IIC通信的SCL以及SDA管脚。
在Pins Grid View中单击勾选PORTD4与PORTD5两个管脚,选择output方式。(可根据自己的需要进行勾选)
在Pins窗口中勾选篇配置PORTD4与PORTD5两个管脚属性。可以在Custom Name中将管脚默认名字重命名为自己想要的名字。(这里将在生成的代码中使用自定义的名字)
完成后点击Generate,然后编译工程,就可以看到MCC已经为我们成功生成代码了。
生成的主要代码如下(主要是定义了IO管脚的一些功能性函数,可直接调用):
// get/set RD4 aliases
#define MI2C_SCL_TRIS TRISDbits.TRISD4
#define MI2C_SCL_LAT LATDbits.LATD4
#define MI2C_SCL_PORT PORTDbits.RD4
#define MI2C_SCL_WPU WPUDbits.WPUD4
#define MI2C_SCL_OD ODCONDbits.ODCD4
#define MI2C_SCL_ANS ANSELDbits.ANSELD4
#define MI2C_SCL_SetHigh() do { LATDbits.LATD4 = 1; } while(0)
#define MI2C_SCL_SetLow() do { LATDbits.LATD4 = 0; } while(0)
#define MI2C_SCL_Toggle() do { LATDbits.LATD4 = ~LATDbits.LATD4; } while(0)
#define MI2C_SCL_GetValue() PORTDbits.RD4
#define MI2C_SCL_SetDigitalInput() do { TRISDbits.TRISD4 = 1; } while(0)
#define MI2C_SCL_SetDigitalOutput() do { TRISDbits.TRISD4 = 0; } while(0)
#define MI2C_SCL_SetPullup() do { WPUDbits.WPUD4 = 1; } while(0)
#define MI2C_SCL_ResetPullup() do { WPUDbits.WPUD4 = 0; } while(0)
#define MI2C_SCL_SetPushPull() do { ODCONDbits.ODCD4 = 0; } while(0)
#define MI2C_SCL_SetOpenDrain() do { ODCONDbits.ODCD4 = 1; } while(0)
#define MI2C_SCL_SetAnalogMode() do { ANSELDbits.ANSELD4 = 1; } while(0)
#define MI2C_SCL_SetDigitalMode() do { ANSELDbits.ANSELD4 = 0; } while(0)
// get/set RD5 aliases
#define MI2C_SDA_TRIS TRISDbits.TRISD5
#define MI2C_SDA_LAT LATDbits.LATD5
#define MI2C_SDA_PORT PORTDbits.RD5
#define MI2C_SDA_WPU WPUDbits.WPUD5
#define MI2C_SDA_OD ODCONDbits.ODCD5
#define MI2C_SDA_ANS ANSELDbits.ANSELD5
#define MI2C_SDA_SetHigh() do { LATDbits.LATD5 = 1; } while(0)
#define MI2C_SDA_SetLow() do { LATDbits.LATD5 = 0; } while(0)
#define MI2C_SDA_Toggle() do { LATDbits.LATD5 = ~LATDbits.LATD5; } while(0)
#define MI2C_SDA_GetValue() PORTDbits.RD5
#define MI2C_SDA_SetDigitalInput() do { TRISDbits.TRISD5 = 1; } while(0)
#define MI2C_SDA_SetDigitalOutput() do { TRISDbits.TRISD5 = 0; } while(0)
#define MI2C_SDA_SetPullup() do { WPUDbits.WPUD5 = 1; } while(0)
#define MI2C_SDA_ResetPullup() do { WPUDbits.WPUD5 = 0; } while(0)
#define MI2C_SDA_SetPushPull() do { ODCONDbits.ODCD5 = 0; } while(0)
#define MI2C_SDA_SetOpenDrain() do { ODCONDbits.ODCD5 = 1; } while(0)
#define MI2C_SDA_SetAnalogMode() do { ANSELDbits.ANSELD5 = 1; } while(0)
#define MI2C_SDA_SetDigitalMode() do { ANSELDbits.ANSELD5 = 0; } while(0)
完成后将OLED模块附带的STM32F103的几个头文件以及源文件添加到OLED文件夹中:
将oled.h中的代码
//-----------------OLED IIC端口定义----------------
#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//SCL
#define OLED_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)
#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//SDA
#define OLED_SDIN_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)
替换为:
#define OLED_SCLK_Clr() MI2C_SCL_SetLow()//SCL
#define OLED_SCLK_Set() MI2C_SCL_SetHigh()
#define OLED_SDIN_Clr() MI2C_SDA_SetLow()//SDA
#define OLED_SDIN_Set() MI2C_SDA_SetHigh()
然后就可以像STM32单片机一样使用该OLED模块了,调用oled.c文件中的相关函数即可。经过测试,会出现无法使用的问题,需要在几个函数中增加一个1us的延时即可使用(注意:延时函数需要使用调用system.h文件才能正常使用,不然会报错):
void IIC_Start()
{
OLED_SCLK_Set();
OLED_SDIN_Set();
__delay_us(1);
OLED_SDIN_Clr();
OLED_SCLK_Clr();
}
/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{
OLED_SCLK_Set() ;
OLED_SDIN_Clr();
OLED_SDIN_Set();
}
void IIC_Wait_Ack()
{
OLED_SCLK_Set();
__delay_us(1);
OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
OLED_SCLK_Clr();
for(i=0;i<8;i++)
{
m=da;
// OLED_SCLK_Clr();
m=m&0x80;
if(m==0x80)
{OLED_SDIN_Set();}
else OLED_SDIN_Clr();
da=da<<1;
OLED_SCLK_Set();
__delay_us(1);
OLED_SCLK_Clr();
}
运行结束后OLED模块即可显示用户需要的图文信息。