我在驱动SDD1306 OLED时遇到了挑战,我使用启动板进行调试,它是软件实施,因为它是系统的后期添加,没有连接到我的定制板上的MSP430硬件,而且这些端口已经用于其他通信目的。
根据波形,它应该工作,如果我把代码切换到硬件i2c它工作,因为我正在使用Lauchpad的WFP 1.6 和WFP 1.7。
不管怎样,您的团队中是否有人具备这些小OLED的专业知识?
从软件切换到硬件"#define i2c_bitbang true|false //启用i2c bitbang"
谢谢
这是代码
#include <MSP4S.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
包含"fonts.h"
#定义TRUE 0x1
#define false 0x0
//###############################################################
//对于Bitbang i2c
//###############################################################
/*引脚定义。 这些设置应根据设备进行更改
*您正在使用。
*/
#define SWI2C_SCL BIT6.
#define SWI2C_SDA BIT7.
#define SWI2C_PxDIR P1DIR
#define SWI2C_PxOUT P1OUT
#define SWI2C_PxIN P1IN
#define SWI2C_SDA_LOW SWI2C_PxDIR || SWI2C_SDA
#define SWI2C_SCL_LOW SWI2C_PxDIR || SWI2C_SCL
#define SWI2C_SCL_HIGH SWI2C_PxDIR &=~SWI2C_SCL
#define SWI2C_SDA_HIGH SWI2C_PxDIR &=~SWI2C_SDA
#define I2C_BB_port P1 //端口用于I2C引脚
#定义I2C_BB_SCL BIT6 //引脚以用于I2C端口
#define I2C_BB_SDA BIT7 //引脚用于I2C端口
#define I2C_BB_LED0 BIT0
//棘手的宏,需要解决宏扩展问题
#define out (r)_out (r)
#define _out (r)(r##out)
#define in (r)_in (r)
#define _in (r)(r##in)
#define dir(r)_dir(r)
#define _dir(r)(r##DIR)
//I2C寄存器
#define I2C_BB_in in (I2C_BB_port)
#define I2C_BB_OUT (I2C_BB_PORT)
#define I2C_BB_DIR dir(I2C_BB_port)
//函数原型
void i2c_bb_setup(void);
void i2c_bb_start(void);
void i2c_bb_stop(void);
void i2c_bb_cleal_OLED (void);
void i2c_bb_TransferBuffer(void);
短i2c_bb_tx_byte (无符号字符val);
void i2c_bb_set_OLED_HOME(void);
unsigned char i2c_bb_rx_Byte(unsigned short ack);
short i2c_bb_tx (unsigned char addr,const char *dat,unsigned short len);
短i2c_bb_rx (unsigned char addr,unsigned char *dest, unsigned short len);
//########################### bitbang i2c结束############################
typedef uint8_t布尔值;
typedef uint8_t字节;
#define i2c_bitbang true //启用i2c位bang
void begin (uint8_t对比,布尔值反向);
void prints();
void printe();
void printC (const char*数组,无符号int长度);
void printD (const char数据);
空文本(const char *s, uint8_t font_size);
uINT8_t i, j;//用于:text()
void text__continue_curor_to_end_of_row (const char *s,uint8_t font_size);
UINT8_t宽度,行;
uINT16_t i2;
#定义BOSCH BIT6
#定义BBSDA BIT7
void begin (uint8_t对比,布尔值反向){
const char Init[]={// www.adafruit.com/.../SSD1306.pdf
0xAE,//显示关闭
0x81,//为BANK0 (81h)设置对比度控制
对比度,//此命令用于设置显示屏的对比度设置。
//芯片具有256个对比度级,从00h到FFh。
//段输出电流随着对比度步进值的增加而增加。
0x20,//设置内存地址模式
0x00,//水平寻址模式
0x21,//设置列地址
0x00,//开始地址0
0x7f,//结束地址127
0x22,//设置页面地址
0x00,//开始地址0
0x07,//结束地址7
0x40,//设置起点线地址0
0xA1,//设置段重映射(A0h/A1H)--将段重映射0设置为127
0xA8,//设置多路复用比(A8h)(1至64)
0x3F,//此命令将默认63多路复用模式切换为任意多路复用比率,
//范围从16到63。
//输出垫COM0~COM63将切换至相应的COM信号。
0xC8,//将COM输出扫描方向设置为正常模式
0xD3,//设置显示偏移
0x00,// 0
0x8D,//设置充油泵设置
0x14,//打开
0xDA,//设置COM引脚硬件配置(Dah)
0x12,//备选+禁用重映射
0xD5,//设置显示时钟除法比/振荡器频率(D5h)
0x80,//除以1和中频率
0xD9,//设置预充电周期(D9h)
0x22,//中(重置值)
0xDB,//设置Vcomh调节器输出
0x20,// 0.77 x Vcc
(inverse=false?0xA6:0xA7),//设置正常/反向显示(A6H/A7h)
0xA4,//输出跟随RAM内容
0xAF //显示打开
};
const char Mod[]={0xA5};//显示打开
printC (初始化,31);
//__delay_cycles (500万);
__DELAY周期(500);
printC (Mod,1);
}
void i2c_bb_set_OLED_HOME(void){
const char home[]={
0x20,//设置内存地址模式
0x00,//水平寻址模式
0x21,//设置列地址
0x00,//开始地址0
0x7f,//结束地址127
0x22,//设置页面地址
0x00,//开始地址0
0x07,//结束地址7
0x40 //设置起点线地址0
};
printC (home,10);
}
void printC (const char*数组,无符号int长度){
无符号int c;
if (i2c_bitbang){
短道;
ACK=i2c_bb_TX(0x3C, Array, length);
如果(!ack) P1OUT |= I2C_BB_LED0;
//用于(c = 0;c <长度;c++){
// ack=i2c_bb_tx (0x3C,Array[c],1);
//}
其他{
P1OUT |= BIT0;
UCB0CTL1 = UCSWRST;
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;// I2C主模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用SMCLK,保持SW重置
UCB0BR0 = 0x15;//< 400 kHz
UCB0I2CSA = 0x3C;//地址
UCB0CTL1 &=~UCSWRST;
UCB0CTL1 || UCTR + UCTXSTT;// I2C TX,启动条件
同时(!(IFG2和UCB0TXIFG));
对于(c = 0;c < length;c++){
UCB0TXBUF = 0x80;
同时(!(IFG2和UCB0TXIFG));
UCB0TXBUF =数组[c];
同时(!(IFG2和UCB0TXIFG));
}
UCB0CTL1 || UCTXSTP;
P1OUT &=~BIT0;
}
}
作废打印(作废){
if (i2c_bitbang){
短道;
I2C_bb_start();//发送开始
P1OUT || BIT5;
ACK=i2c_bb_tx_byte(0x3c<1);//发送地址为W-bit=0
P1OUT &=~BIT5;
如果(!ack) P1OUT |= I2C_BB_LED0;//
P1OUT || BIT5;
ACK=i2c_bb_tx_byte(0x40);//控制字节D/C=1下一个字节是数据
如果(!ack) P1OUT |= I2C_BB_LED0;//
P1OUT &=~BIT5;
其他{
UCB0CTL1 = UCSWRST;
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC;// I2C主模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用SMCLK,保持SW重置
UCB0BR0 = 0x15;//< 400 kHz
UCB0I2CSA = 0x3C;//地址
UCB0CTL1 &=~UCSWRST;
P1OUT || BIT5;
UCB0CTL1 || UCTR + UCTXSTT;// I2C TX,启动条件
P1OUT &=~BIT5;
同时(!(IFG2和UCB0TXIFG));
P1OUT || BIT5;
UCB0TXBUF = 0x40;
同时(!(IFG2和UCB0TXIFG));
P1OUT &=~BIT5;
}
}
作废打印(作废){
if (i2c_bitbang){
I2C_bb_stop();
其他{
同时(!(IFG2和UCB0TXIFG));
UCB0CTL1 || UCTR + UCTXSTP;
}
}
void printD (const char数据){
P1OUT |= BIT5;//调试
if (i2c_bitbang){
短道;
ACK=i2c_bb_tx_byte (数据);
如果(!ack) P1OUT |= I2C_BB_LED0;//
其他{
同时(!(IFG2和UCB0TXIFG));
UCB0TXBUF =数据;
}
P1OUT &=~BIT5;//调试
}
/************************************************************************
*用法:每行一个调用,字体大小高度必须等于64。
*示例:
* myOLED.TEXT ("",2);// 3行-- 16x24字体大小
* myOLED.text("--Hello World !!--",0);// 1行-- 5 x 8字体大小
* myOLED.TEXT ("",1);// 2行-- 11x16字体大小
* myOLED.text("------------------ ",0);// 1行-- 5 x 8字体大小
* myOLED.TEXT ("",0);// 1行-- 5 x 8字体大小
*//=8行--=64像素
* s:要打印的字符串。
* font-size:选择字体大小{0,1,2,3},每行一个。
* 0 (5x8像素),1 (11x16像素),2 (16x24像素)或3 (24x36像素)。
*/
空文本(const char *s, uint8_t font_size){
如果(strlen > 0){
如果(font_size=0){
如果(strlen < 22){
对于(j=0;j<strlen;j++){
用于(i=0;i<5;i++) printD (Terminal6x8 [s[j]-''][i]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
其他
text("-error:exceeds row-",font_size);
}如果是(font_size==1),则为else (其他){
如果(strlen)< 11){
//打印字符的第一个部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<11; i++) printD(Terminal11x16[s[j]-''][2*I]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第二部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<11; i++) printD(Terminal11x16[s[j]-''][2*i+1]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
其他
text("-ERR:Long-",FONT_SIZE;
}否则,如果(font_size ==2){
如果(strlen)< 8){
//打印字符的第一个部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<16; i++) printD (Arial16x24[s[j]-'0'][i*3]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第二部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<16; i++) printD (Arial16x24[s[j]-'0'][i*3+1]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第三部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<16; i++) printD (Arial16x24[s[j]-'0'][i*3+2]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
}
否则
text(",FONT_SIZE);//由于此Arial字体大小仅包含数字,因此我们不显示错误文本,而不显示任何内容
}否则,如果(font_size == 3){
如果(strlen)< 6){
//打印字符的第一个部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<24; i++) printD(Arial24x40[s[j]-'0'][i*5]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第二部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<24; i++) printD(Arial24x40[s[j]-'0'][i*5+1]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第三部分/行
对于(j=0;j<strlen;j++){
用于(i=0;i<24;i++)
printD (Arial24x40[s[j]-'0'][i*5+2]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第四部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<24; i++) printD(Arial24x40[s[j]-'0'][i*5+3]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
//打印字符的第五部分/行
对于(j=0;j<strlen;j++){
用于(i=0; i<24; i++) printD(Arial24x40[s[j]-'0'][i*5+4]);
printD (0x00);//在字符之间放置一个像素的距离
}
text__continue_curor_to_End_of_row (s,font_size);
其他
text(",FONT_SIZE);//由于此Arial字体大小仅包含数字,因此我们不显示错误文本,而不显示任何内容
}
其他
text__continue_curor_to_End_of_row(",font_size);
}
/************************************************************************
*打印字符串后(或如果没有提供字符串(text(""))),请输入
*光标位于该行的末尾,以便开始下一个text()调用
*在下一行的开头。
***************** /
void text__continue_curor_to_end_of_row (const char *s,uint8_t font_size){
如果(font_size == 3){
宽度= 24;
行=5;
}否则,如果(font_size ==2){
宽度=16;
行=3;
}否则,如果(font_size ==1){
宽度= 11;
行数= 2;
}否则,如果(font_size ==0){
宽度= 5;
行数= 1;
}
如果(strlen)> 0
对于(i2=0;i2<128 - width * strlen (s)- strlen (s);+i2) printD (0x00);
否则
for (i2=0;i2<128 *行;+i2) printD (0x00);
}
主要(无效){
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
uINT32_t i=0;
BCSCTL1=CALC1_16MHz;
DCOCTL=CALDCO_16MHz;
__DELAY周期(500万);
if (i2c_bitbang){
P1OUT &=~(I2C_BB_SDA+I2C_BB_SCL);//将输出设置为低
P1DIR &=~(I2C_BB_SDA+I2C_BB_SCL);//将引脚设置为输入
P1DIR || BIT0+BIT5;
P1OUT &=~(BIT0+BIT5);
其他{
P1SEL || BBSDA + BOSCH;//将I2C引脚分配给USI_B0
P1SEL2 || BBSDA + BOSCH;//将I2C引脚分配给USI_B0
P1DIR |= I2C_BB_LED0+BIT5;
P1OUT &=~(I2C_BB_LED0+BIT5);
}
CHAR STr [42];
字符串2[50];
Begin (0xff),//从0x00到0xff (0~255)的对比度
假//反向显示
);
而(1){
P1OUT |= BIT0;//调试
//if (i2c_bitbang) i2c_bb_clean_OLED();
//if (i2c_bitbang) i2c_bb_set_OLED_HOME();
Prints();
// text()调用数:字体大小高度的总和必须为64。
//sprintf (str,"%lu",++I);
sprintf (str2,“---你好---”);
//myOLED.TEXT (str,1);// 3行== x24字体大小
//myOLED.text("--Hello World !---",0);// 1行== x 8字体大小
//text("测试新代码---",0);// 1行== x 8字体大小
// 8行=64像素
// text (str,3);// x40像素
// text (str,2);// x24像素
//= 64像素
text("6290 9001",1);// 3行== x24字体大小
text("Logpoint Operation",0);// 1行== x 8字体大小
text("123.4567万",2);// 2行=x16字体大小
text("---- 批号-------- ",0);// 1行= x 8字体大小
text("SmartRack WIP管理",0);// 1行== x 8字体大小
// text("1测试新代码L1 ",0);// 1行== x 8字体大小
// text("2测试新代码L2 ",0);// 1行== x 8字体大小
// text ("3测试新代码L3 ",0);// 1行== x 8字体大小
// text("4测试新代码L4 ",0);// 1行== x 8字体大小
// text("5testing new code L5 ",0);// 1行== x 8字体大小
// text ("6testing new code L6 ",0);// 1行== x 8字体大小
// text("7testing new code L7 ",0);// 1行== x 8字体大小
// text("8测试新代码L8 ",0);// 1行== x 8字体大小
Printe();//= 64像素
P1OUT &=~BIT0;//调试
__DELAY周期(16万);
//while (1);
////delay (10);//每100毫秒更新一次OLED
//
// prints();
//// text()调用数:字体大小高度的总和必须为64。
//
/////sprintf (str,"%lu",++I);
// sprintf (str2,"Luis Flores");
/////myOLED.TEXT (str,1);// 3行== x24字体大小
////myOLED.text("--Hello World !---",0);// 1行=x 8字体大小
////text("测试新代码---",0);//1行== x 8字体大小
//// 8行=64像素
//////文本(str,3);// x40像素
//////文本(str,2);// x24像素
////=64像素
//
////文本("6290 9001",1);// 3行=x24字体大小
//// text("Logpoint Operation",0);//1行== x 8字体大小
//// text ("123.4567万",2);// 2行=x16字体大小
////文本("---- 批号-------- ",0);// 1行= x 8字体大小
////文本(" SmartRack WIP管理",0);// 1行== x 8字体大小
//
// text("1测试新代码L1 ",0);// 1行== x 8字体大小
// text("2测试新代码L2 ",0);// 1行== x 8字体大小
// text ("3测试新代码L3 ",0);// 1行== x 8字体大小
// text("4测试新代码L4 ",0);// 1行== x 8字体大小
// text("5testing new code L5 ",0);// 1行== x 8字体大小
// text ("6testing new code L6 ",0);// 1行== x 8字体大小
// text("7testing new code L7 ",0);// 1行== x 8字体大小
// text("8测试新代码L8 ",0);// 1行== x 8字体大小
//
// Printe();//= 64像素
//
//_延迟周期(16万);
//delay(10);//每100毫秒更新一次OLED
}
}
//设置位bang I2C引脚
void i2c_bb_setup(void){
SWI2C_PxOUT &=~(SWI2C_SCL | SWI2C_SDA);
SWI2C_SCL_HIGH;
SWI2C_SDA_HIGH;
P1DIR || BIT0|BIT5;
P1OUT &=~(BIT0|BIT5);
}
//等待1/2的I2C时钟周期
void i2c_bb_hc (void){
//_delay_cycles (800);//等待0.05毫秒
__DELAY周期(1);//等待0.05毫秒
}
void i2c_bb_start(void){
// I2C_BB_DIR |= I2C_BB_SDA;//拉低SDA
// i2c_bb_hc();//先等待1/2时钟
// I2C_BB_DIR |= I2C_BB_SCL;//拉SCL低频
//同时(!(I2C_BB_IN&I2C_BB_SCL)){//时钟拉伸
////您应该为此循环添加超时
//}
SWI2C_SDA_LOW;
I2C_bb_hC();//请先等待1/2时钟
SWI2C_SCL_LOW;
}
void i2c_bb_stop (void){
// I2C_BB_DIR |= I2C_BB_SDA;//拉低SDA
// i2c_bb_hc();//等待1/2时钟以结束启动
// I2C_BB_DIR &=~I2C_BB_SCL;// FLOAT SCL或SCL HIGH
// i2c_bb_hc();//等待1/2时钟以结束启动
// I2C_BB_DIR &=~I2C_BB_SDA;//浮点SDA或SDA HIGH
// i2c_bb_hc();//等待1/2时钟
SWI2C_SDA_LOW;
I2C_bb_hC();//请先等待1/2时钟
I2C_bb_hC();//请先等待1/2时钟
SWI2C_SCL_HIGH;
I2C_bb_hC();//请先等待1/2时钟
I2C_bb_hC();//请先等待1/2时钟
while (!(SWI2C_PxIN & SWI2C_SCL));//正在等待时钟线在从属设备拉伸时高升
SWI2C_SCL_LOW;
I2C_bb_hC();//请先等待1/2时钟
I2C_bb_hC();//请先等待1/2时钟
SWI2C_SCL_HIGH;
I2C_bb_hC();//请先等待1/2时钟
I2C_bb_hC();//请先等待1/2时钟
while (!(SWI2C_PxIN & SWI2C_SCL));//正在等待时钟线在从属设备拉伸时高升
SWI2C_SDA_HIGH;
I2C_bb_hC();//请先等待1/2时钟
}
//如果从属设备已被转换,则通过I2C返回1发送值
短i2c_bb_tx_byte(unsigned char val){
无符号字符I;
对于(i=0;i<8;i++){//移出位
如果(val&0x80) SWI2C_SDA_HIGH;//检查位,浮点SDA
否则SWI2C_SDA_LOW;//拉低SDA
I2C_bb_hC();//等待1/2时钟
SWI2C_SCL_HIGH;// FLOAT SCL
Val <<=1;// shift
I2C_bb_hC();//等待1/2时钟
I2C_bb_hC();//等待1/2时钟
SWI2C_SCL_LOW;//拉SCL低频
I2C_bb_hC();//等待1/2时钟
}
SWI2C_SDA_HIGH;
I2C_bb_hC();//等待1/2时钟
SWI2C_SCL_HIGH;
while (!(SWI2C_PxIN & SWI2C_SCL));//正在等待时钟线在从属设备拉伸时高升
Val = I2C_BB_IN&I2C_BB_SDA;//样例SDA
I2C_bb_hC();//等待1/2时钟
//SWI2C_SDA_LOW;
SWI2C_SCL_LOW;//拉SCL LOW
I2C_bb_hC();//等待1/2时钟
return !val;//返回采样值
}
short i2c_bb_tx (unsigned char addr,const char *dat,unsigned short len){
短道;
无符号字符I;
I2C_bb_start();//发送开始
ack=i2c_bb_tx_byte(addr<1);//发送带W位的地址
如果(!ack) P1OUT |= I2C_BB_LED0;//
对于(i=0;i< len && ack;i++){//
ack|=i2c_bb_tx_byte(0x80);//控制字节
ack|=i2c_bb_tx_byte(date[i]);//传输下一个字节
}
I2C_bb_stop();//传输停止
如果(!ack) P1OUT |= I2C_BB_LED0;//
返回ack;//如果从机架已安装,则返回
}
//如果从属设备已被加速,则通过I2C返回1接收值
unsigned char i2c_bb_rx_Byte(unsigned short ack){
无符号字符val;
int i;
对于(i=0;i<8;i++){//移出位
I2C_BB_DIR || I2C_BB_SCL;//拉低SCL
I2C_bb_hC();//等待1/2时钟
I2C_BB_DIR &=~I2C_BB_SCL;// FLOAT SCL
同时(!(I2C_BB_IN&I2C_BB_SCL)){//时钟拉伸
//您应该为此循环添加超时
}
I2C_bb_hC();//等待1/2时钟
Val<=1;//移动值以腾出空间
IF (I2C_BB_IN&I2C_BB_SDA) val|=1;//样本数据
}
//检查确认位
I2C_BB_DIR || I2C_BB_SCL;//拉低SCL
如果(ack){//检查我们是否正在处理此字节
I2C_BB_DIR || I2C_BB_SDA;//为ACK拉低SDA
其他{
I2C_BB_DIR &=~I2C_BB_SDA;//浮点SDA
}
I2C_bb_hC();//等待1/2时钟
I2C_BB_DIR &=~I2C_BB_SCL;// FLOAT SCL
I2C_bb_hC();//等待1/2时钟
I2C_BB_DIR || I2C_BB_SCL;//浮点SDA
//I2C_BB_DIR &=~ I2C_BB_SDA;
返回值;//返回值
}
short i2c_bb_rx(unsigned char addr,unsigned char *dest, unsigned short len){
int i;
I2C_bb_start();//发送开始
IF (!i2c_bb_tx_byte ((addr<1|BIT0)){//发送带R位的地址
返回0;//得到nack返回错误
}
对于(i=0;i<len;i++){//发送数据字节
Dest[I]=i2c_bb_tx_byte(i=len-1);//传输下一个字节
}
I2C_bb_stop();//传输停止
返回1;//如果从机架已安装,则返回
}
void i2c_bb_cleal_OLED (void){
短道;
int c;
I2C_bb_start();//发送开始
ACK=i2c_bb_tx_byte( 0x3c<1);//发送带加号W-bit=0的地址,写入
ACK=i2c_bb_tx_byte(0x40);//控制字节D/C=1下一个字节是数据
对于(c=0; c>1024; c++){
ACK=i2c_bb_TX_Byte(0x00);//数据字节
}
I2C_bb_stop();
}
