現在有了具體的I2C通信器件,一塊1.3寸OLED屏幕,今日嘗試移植配置一下:
本文主要講的是,使用軟件模擬I2C通信
文章提供測試代碼講解、完整工程下載、測試效果圖
目錄
前置文章:
I2C通信引腳:
軟件I2C 引腳的初始化:
I2C_software.h
#include "OLED.h"
#include "OLED_ZK.h"
主函數文件:
測試效果:
有關軟件I2C是否需要關總中斷的測評與感受:
測試工程下載:
我的單片機平臺是這個:
前置文章:
TMS320F28P550SJ9學習筆記8:I2C通信的結構體寄存器配置的了解-CSDN博客
I2C通信引腳:
GPIO10 ???? SDA
GPIO11 ???? SCL
軟件I2C 引腳的初始化:
這里主要注意幾個方面:
1.都要有上拉電阻? 2.引腳速率? 3. SDA方向可變
I2C總線速度可以是標準速率(100 kHz)、快速速率(400 kHz)或更高。引腳的速度設置應至少能滿足I2C總線速率的要求。
?
I2C_software.h
這里初始化I2C的引腳,寫了一些I2C的基本模擬函數
/** I2C_software.h** Created on: 2025年3月11日* Author: 30313*/#ifndef USER_I2C_SOFTWARE_H_
#define USER_I2C_SOFTWARE_H_#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"#define u8 unsigned char//宏定義 設定寄存器來改變SDA線的輸入輸出狀態:
#define SDA_IN() {EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO10 = 0; EDIS;} //SDA輸入模式
#define SDA_OUT() {EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO10 = 1; EDIS;} //SDA輸出模式static inline void setIIC_SDA(Uint16 value) {if (value) { GpioDataRegs.GPASET.bit.GPIO10 = 1; }// GPIO10 輸出1else { GpioDataRegs.GPACLEAR.bit.GPIO10 = 1; } // GPIO10 輸出0
}static inline void setIIC_SCL(Uint16 value) {if (value) { GpioDataRegs.GPASET.bit.GPIO11 = 1; } // GPIO11 輸出1else { GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; } // GPIO11 輸出0
}//IO操作函數
#define IIC_SCL setIIC_SCL
#define IIC_SDA setIIC_SDA
#define READ_SDA GpioDataRegs.GPADAT.bit.GPIO10void Init_I2C_software(void); //初始化軟件I2Cvoid I2C_Start(void); //產生IIC起始信號
void I2C_Stop(void); //產生IIC停止信號
u8 I2C_Wait_Ack(void);//等待應答信號到來
void I2C_Ack(void); //產生ACK應答
void I2C_NAck(void); //不產生ACK應答
void I2C_Send_Byte(u8 txd); //IIC發送一個字節
u8 I2C_Read_Byte(unsigned char ack); //讀1個字節,ack=1時,發送ACK,ack=0,發送nACK#endif /* USER_I2C_SOFTWARE_H_ */
/** I2C_software.c** Created on: 2025年3月11日* Author: 30313*/#include "I2C_software.h"//軟件I2C 初始化 SCL GPIO10 SDA GPIO11
void Init_I2C_software(void)
{//設置GPIO10和GPIO11為GPIO模式EALLOW;GpioCtrlRegs.GPAGMUX1.bit.GPIO10 = 0;// 將A17/GPIO10設置為GPIO模式GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0; // 將B17/GPIO11設置為GPIO模式//禁用模擬//GpioCtrlRegs.GPAAMSEL.bit.GPIO10 = 0; // 禁用GPIO10的模擬功能GpioCtrlRegs.GPAAMSEL.bit.GPIO11 = 0; // 禁用GPIO11的模擬功能//設置GPIO10和GPIO11為輸出GpioCtrlRegs.GPADIR.bit.GPIO10 = 1; // 設置GPIO10為輸出GpioCtrlRegs.GPADIR.bit.GPIO11 = 1; // 設置GPIO11為輸出//設置GPIO10和GPIO11為標準輸入/輸出模式GpioCtrlRegs.GPAPUD.bit.GPIO10 = 1; // 啟用GPIO10的上拉電阻GpioCtrlRegs.GPAPUD.bit.GPIO11 = 1; // 啟用GPIO11的上拉電阻//設置GPIO10和GPIO11為同步模式(可選)GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0; // 設置GPIO10為同步模式GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0; // 設置GPIO11為同步模式//GpioCtrlRegs.GPACTRL.bit.QUALPRD2=0x01 // 設置GPIO16~23 的 采樣周期為 PLLSYSCLK/2EDIS;//SDA_OUT();
}//產生IIC起始信號
void I2C_Start(void)
{SDA_OUT(); //sda線輸出IIC_SDA(1);IIC_SCL(1);DEVICE_DELAY_US(4);IIC_SDA(0);//START:when CLK is high,DATA change form high to lowDEVICE_DELAY_US(4);IIC_SCL(0);//鉗住I2C總線,準備發送或接收數據
}
//產生IIC停止信號
void I2C_Stop(void)
{SDA_OUT();//sda線輸出IIC_SCL(0);IIC_SDA(0);//STOP:when CLK is high DATA change form low to highDEVICE_DELAY_US(4);IIC_SCL(1);IIC_SDA(1);//發送I2C總線結束信號DEVICE_DELAY_US(4);
}
//等待應答信號到來
//返回值:1,接收應答失敗
// 0,接收應答成功
u8 I2C_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN(); //SDA設置為輸入IIC_SDA(1);DEVICE_DELAY_US(1);IIC_SCL(1);DEVICE_DELAY_US(1);while(READ_SDA){ucErrTime++;if(ucErrTime>250){I2C_Stop();return 1;}}IIC_SCL(0);//時鐘輸出0return 0;
}
//產生ACK應答
void I2C_Ack(void)
{IIC_SCL(0);SDA_OUT();IIC_SDA(0);DEVICE_DELAY_US(2);IIC_SCL(1);DEVICE_DELAY_US(2);IIC_SCL(0);
}
//不產生ACK應答
void I2C_NAck(void)
{IIC_SCL(0);SDA_OUT();IIC_SDA(1);DEVICE_DELAY_US(2);IIC_SCL(1);DEVICE_DELAY_US(2);IIC_SCL(0);
}
//IIC發送一個字節
//返回從機有無應答
//1,有應答
//0,無應答
void I2C_Send_Byte(u8 txd)
{u8 t;SDA_OUT();IIC_SCL(0);//拉低時鐘開始數據傳輸for(t=0;t<8;t++){//IIC_SDA=(txd&0x80)>>7;if((txd&0x80)>>7)IIC_SDA(1);elseIIC_SDA(0);txd<<=1;DEVICE_DELAY_US(2); //對TEA5767這三個延時都是必須的IIC_SCL(1);DEVICE_DELAY_US(2);IIC_SCL(0);DEVICE_DELAY_US(2);}
}//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK
u8 I2C_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDA設置為輸入for(i=0;i<8;i++ ){IIC_SCL(0);DEVICE_DELAY_US(2);IIC_SCL(1);receive<<=1;if(READ_SDA)receive++;DEVICE_DELAY_US(1);}if (!ack)I2C_NAck();//發送nACKelseI2C_Ack(); //發送ACKreturn receive;
}
#include "OLED.h"
這里主要是OLED的一些操作函數,要與我配置的I2C引腳聯系起來
#ifndef _OLED_h_
#define _OLED_h_#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"#include "OLED_ZK.h"
#include "I2C_software.h"#define OLED_MODE 0
#define SIZE 8
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF
#define X_WIDTH 128
#define Y_WIDTH 64
//-----------------OLED IIC端口定義---------------- #define OLED_SCLK_Clr() IIC_SCL(0)//SCL
#define OLED_SCLK_Set() IIC_SCL(1)#define OLED_SDIN_Clr() IIC_SDA(0)//SDA
#define OLED_SDIN_Set() IIC_SDA(1)#define OLED_CMD 0 //寫命令
#define OLED_DATA 1 //寫數據//OLED控制用函數
void OLED_WR_Byte(unsigned dat,unsigned cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(u8 x,u8 y,u8 no);
void OLED_ShowCHinese_small(u8 x,u8 y,u8 no);
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);void Delay_50ms(unsigned int Del_50ms);
void Delay_1ms(unsigned int Del_1ms);void fill_picture(unsigned char fill_Data);
void Picture(void);
void IIC_Start(void);
void IIC_Stop(void);
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);
void Write_IIC_Byte(unsigned char IIC_Byte);void IIC_Wait_Ack(void);#endif
#include "OLED.h"//OLED的顯存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
/**********************************************
//IIC Start
**********************************************/
/**********************************************
//IIC Start
**********************************************/
void IIC_Start(void)
{OLED_SCLK_Set() ;OLED_SDIN_Set();OLED_SDIN_Clr();OLED_SCLK_Clr();
}/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop(void)
{OLED_SCLK_Set() ;
// OLED_SCLK_Clr();OLED_SDIN_Clr();OLED_SDIN_Set();}void IIC_Wait_Ack(void)
{OLED_SCLK_Set() ;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();OLED_SCLK_Clr();}}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{IIC_Start();Write_IIC_Byte(0x78); //Slave address,SA0=0IIC_Wait_Ack(); Write_IIC_Byte(0x00); //write commandIIC_Wait_Ack(); Write_IIC_Byte(IIC_Command); IIC_Wait_Ack(); IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{IIC_Start();Write_IIC_Byte(0x78); //D/C#=0; R/W#=0IIC_Wait_Ack(); Write_IIC_Byte(0x40); //write dataIIC_Wait_Ack(); Write_IIC_Byte(IIC_Data);IIC_Wait_Ack(); IIC_Stop();
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{if(cmd){Write_IIC_Data(dat);}else {Write_IIC_Command(dat);}}/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{unsigned char m,n;for(m=0;m<8;m++){OLED_WR_Byte(0xb0+m,0); //page0-page1OLED_WR_Byte(0x02,0); //low column start addressOLED_WR_Byte(0x10,0); //high column start addressfor(n=0;n<128;n++){OLED_WR_Byte(fill_Data,1);}}
}/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{unsigned int m;for(;Del_50ms>0;Del_50ms--)for(m=6245;m>0;m--);
}void Delay_1ms(unsigned int Del_1ms)
{unsigned char j;while(Del_1ms--){ for(j=0;j<123;j++);}
}//坐標設置void OLED_Set_Pos(unsigned char x, unsigned char y)
{ OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte((((x+2)&0xf0)>>4)|0x10,OLED_CMD);OLED_WR_Byte(((x+2)&0x0f),OLED_CMD);
}
//開啟OLED顯示
void OLED_Display_On(void)
{OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令OLED_WR_Byte(0X14,OLED_CMD); //DCDC ONOLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//關閉OLED顯示
void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFFOLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}//清屏函數,清完屏,整個屏幕是黑色的!和沒點亮一樣!!!
void OLED_Clear(void)
{ u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //設置頁地址(0~7)OLED_WR_Byte (0x02,OLED_CMD); //設置顯示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD); //設置顯示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新顯示
}
void OLED_On(void)
{ u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //設置頁地址(0~7)OLED_WR_Byte (0x02,OLED_CMD); //設置顯示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD); //設置顯示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); } //更新顯示
}
//在指定位置顯示一個字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白顯示;1,正常顯示
//size:選擇字體 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{ unsigned char c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>Max_Column-1){x=0;y=y+2;}if(Char_Size ==16){OLED_Set_Pos(x,y); for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);OLED_Set_Pos(x,y+1);for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);}else { OLED_Set_Pos(x,y);for(i=0;i<6;i++)OLED_WR_Byte(F6x8[c][i],OLED_DATA);}
}
//m^n函數
u32 oled_pow(u8 m,u8 n)
{u32 result=1; while(n--)result*=m; return result;
}
//顯示2個數字
//x,y :起點坐標
//len :數字的位數
//size:字體大小
//mode:模式 0,填充模式;1,疊加模式
//num:數值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{ u8 t,temp;u8 enshow=0; for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}else enshow=1; }OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }
}
//顯示一個字符號串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{unsigned char j=0;while (chr[j]!='\0'){ OLED_ShowChar(x,y,chr[j],Char_Size);x+=8;if(x>120){x=0;y+=2;}j++;}
}//顯示漢字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{ u8 t,adder=0;OLED_Set_Pos(x,y); for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);adder+=1;} OLED_Set_Pos(x,y+1); for(t=0;t<16;t++){ OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);adder+=1;}
}
/***********功能描述:顯示顯示BMP圖片128×64起始點坐標(x,y),x的范圍0~127,y為頁的范圍0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{ unsigned int j=0;unsigned char x,y;if(y1%8==0) y=y1/8; else y=y1/8+1;for(y=y0;y<y1;y++){OLED_Set_Pos(x0,y);for(x=x0;x<x1;x++){ OLED_WR_Byte(BMP[j++],OLED_DATA); }}
} void OLED_ShowCHinese_small(u8 x,u8 y,u8 no)
{u8 t,adder=0;OLED_Set_Pos(x,y); for(t=0;t<12;t++){OLED_WR_Byte(Hzk_m[no][t],OLED_DATA);adder+=1;}
}//初始化SSD1306
void OLED_Init(void)
{ DEVICE_DELAY_US(100);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 對比度值設置為128OLED_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(1 to 64) 設置多路復用比率(1到64)OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty 設置Duty值為1/32OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction 設置COM掃描方向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);// 設置振蕩器分頻值為80OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off 設置區域顏色模式關閉OLED_WR_Byte(0x05,OLED_CMD);// 設置區域顏色模式值為05OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period 設置預充電周期OLED_WR_Byte(0xF1,OLED_CMD);// 設置預充電周期值為F1OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion 設置COM引腳配置OLED_WR_Byte(0x12,OLED_CMD);// 設置COM引腳配置值為12OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh 設置VcomhOLED_WR_Byte(0x30,OLED_CMD);// 設置Vcomh值為30OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable 設置充電泵使能OLED_WR_Byte(0x14,OLED_CMD);// 設置充電泵使能值為14OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel 打開顯示屏
}
#include "OLED_ZK.h"
?這是OLED的字庫,里面有我取模過的太空人圖片28張,如果你的flash空間不夠,請將定義的BMP1[]~BMP28[] 數組悉數刪去,不影響其他字符的打印
這里就不貼出?OLED_ZK 的.c文件了,有點大
#ifndef _OLED_ZK_h_
#define _OLED_ZK_h_#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"#define u32 unsigned intextern const unsigned char F6x8[][6];
extern const unsigned char F8X16[];
extern char Hzk[][32];
extern char Hzk_m[][32];extern unsigned char BMP1[];
extern unsigned char BMP2[];
extern unsigned char BMP3[];
extern unsigned char BMP4[];
extern unsigned char BMP5[];
extern unsigned char BMP6[];
extern unsigned char BMP7[];
extern unsigned char BMP8[];
extern unsigned char BMP9[];
extern unsigned char BMP10[];
extern unsigned char BMP11[];
extern unsigned char BMP12[];
extern unsigned char BMP13[];
extern unsigned char BMP14[];
extern unsigned char BMP15[];
extern unsigned char BMP16[];
extern unsigned char BMP17[];
extern unsigned char BMP18[];
extern unsigned char BMP19[];
extern unsigned char BMP20[];
extern unsigned char BMP21[];
extern unsigned char BMP22[];
extern unsigned char BMP23[];
extern unsigned char BMP24[];
extern unsigned char BMP25[];
extern unsigned char BMP26[];
extern unsigned char BMP27[];
extern unsigned char BMP28[];#endif
主函數文件:
這是主函數文件,只要看圖中三個地方,就能啟用OLED打印了:
?
/* 名稱 : 軟件I2C 測試工程* 創建者 : NULL指向我* 日期 : 2025.3.12* 功能 : 軟件模擬I2C 通過1.3寸OLED打印 data counts 計數(每200ms + 1)* 平臺 : LAUNCHXL-F28P55x* 型號 : TMS320F28P550SJ9* 備注 :* IIC_SCL GPIO 10* IIC_SDA GPIO 11* 主函數** *///頭文件
#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"
#include "sci_1.h"
#include "TIMER.h"
#include "string.h"
#include "stdio.h"
#include "I2C_software.h"#include "OLED.h"// 這個 CPU定時器的 中斷服務函數貌似只能 定義在 主函數文件
__interrupt void cpuTimer0ISR(void);
__interrupt void cpuTimer1ISR(void);
__interrupt void cpuTimer2ISR(void);//主函數 main
void main(void)
{char buf[30];int data=0;Device_init(); //初始化系統時鐘Device_initGPIO(); //解鎖GPIO端口Init_GPIO_LEDPort(); //初始化LED端口// @LSPCLK = 37.5 MHz (150 MHz SYSCLK) HBAUD = 0x01 and LBAUD = 0xE7.Init_SCIA(9600,37500000);//初始化SCIInitCpuTimers();//初始化定時器CUPTIMER 0Init_CPU_TIMER(&CpuTimer0, 150, 100);//時鐘來源 SYSCLKOUT 150Mhz / 150分頻 /1000 000計數重載值 / 1000 ms溢出中斷頻率InitPieVectTable();Interrupt_initModule();Interrupt_initVectorTable();// 鏈接 中斷服務函數 ISR functionsEALLOW;PieVectTable.TIMER0_INT = &cpuTimer0ISR;PieVectTable.TIMER1_INT = &cpuTimer1ISR;PieVectTable.TIMER2_INT = &cpuTimer2ISR;EDIS;CpuTimer0Regs.TCR.all = 0x4000;CpuTimer1Regs.TCR.all = 0x4000;CpuTimer2Regs.TCR.all = 0x4000;IER |= M_INT1;IER |= M_INT13;IER |= M_INT14;// Enable TINT0 in the PIE: Group 1 interrupt 7PieCtrlRegs.PIEIER1.bit.INTx7 = 1;Init_I2C_software(); //初始化軟件I2COLED_Init(); //初始化OLED屏幕OLED_Clear(); //清空屏幕數據EINT;ERTM;while(1){data++;sprintf(buf,"data counts: %d",data);OLED_ShowString(2,1,(u8 *)buf,16);DEVICE_DELAY_US(200000);}
}/*
data++;
sprintf(buf,"data counts: %d",data);
OLED_ShowString(2,0,(u8 *)buf,16);
*/// cpuTimer0ISR - CPU Timer0 ISR with interrupt counter
__interrupt void cpuTimer0ISR(void)
{CpuTimer0.InterruptCount++;//DEVICE_DELAY_US(80);PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}// cpuTimer1ISR - CPU Timer1 ISR with interrupt counter
__interrupt void cpuTimer1ISR(void)
{CpuTimer1.InterruptCount++;
}// cpuTimer2ISR CPU Timer2 ISR with interrupt counter
__interrupt void cpuTimer2ISR(void)
{CpuTimer2.InterruptCount++;
}//主文件結尾
測試效果:
OLED正常打印字符:
?
有關軟件I2C是否需要關總中斷的測評與感受:
之前學習軟件I2C時,被提示過需要關閉總中斷,防止I2C傳輸出問題,這里就測試一下,我不關總中斷,會出什么問題
但提前說下結果,對OLED的SSD1306芯片貌似沒有什么影響
?這里開了一個100us 的中斷,每次進中斷阻塞80us的延時:
?
?
?
我的I2C器件除了主循環被打斷,導致打印變慢了,OLED的顯示貌似沒問題:
?
邏輯分析儀測試結果如下:
?
?
?
測試工程下載:
https://download.csdn.net/download/qq_64257614/90477080
?