您的当前位置:首页正文

基于OLED液晶显示器的显示系统

2022-10-09 来源:步旅网


基于OLED液晶显示器的显

示系统

姓名:唐旭晴 学号:110400609 班级:11电子2班

一、实习目的

(1)了解飞思卡尔单片机的基本原理,掌握其基本的工作流程。 (2)了解OLED液晶显示屏的基本原理及用法。

(3)能够熟练使用CodeWarrior软件编写C语言程序,使用BDM仿真器下载

程序。 (4)能够熟练焊接电路板。

二、实验设备与器件

CodeWarrior软件,BDM仿真器,万用电路板,飞思卡尔单片机,OLED液晶显示器

三、实验内容

内容:利用飞思卡尔单片机制作基于OLED液晶显示器的显示系统 要求:用四个按键控制,按下第一个按键显示“北”,按下第二个按键显示“京”,按下第三个按键显示“印刷”,按下第四个按键显示“学院”。 (1)OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。

LCD都需要背光,而OLED不需要,因为它是自发光的。这样同样的显示,OLED效果要来得好一些。以目前的技术,OLED的尺寸还难以大型化,但是分辨率确可以做到很高。我们使用的是ALINETEK的OLED显示模块,该模块有以下特点:

1)模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色。 2)尺寸小,显示尺寸为0.96寸,而模块的尺寸仅为27mm*26mm大小。 3)高分辨率,该模块的分辨率为128*64。

4)多种接口方式,该模块提供了总共4种接口包括:6800、8080两种并行接口方式、4线SPI接口方式以及IIC接口方式。 5)不需要高压,直接接3.3V就可以工作了。

这里我们采用的是4线串行(SPI)方式,4先串口模式使用的信号线有如下几条:

CS:OLED片选信号。 RST(RES):硬复位OLED。

DC:命令/数据标志(0,读写命令;1,读写数据)。

SCLK:串行时钟线。在4线串行模式下,D0信号线作为串行时钟线SCLK。 SDIN:串行数据线。在4线串行模式下,D1信号线作为串行数据线SDIN。 模块的D2需要悬空,其他引脚可以接到GND。在4线串行模式下,只能往模块写数据而不能读数据。

在4线SPI模式下,每个数据长度均为8位,在SCLK的上升沿,数据从SDIN移入到SSD1306,并且是高位在前的。DC线还是用作命令/数据的标志线。在4线SPI模式下,写操作的时序如图17.1.6所示:

4线SPI写操作时序图

模块的显存:

SSD1306的显存总共为128*64bit大小,SSD1306将这些显存分为了8页,其对应关系如下表所示:

SSD1306显存与屏幕对应关系表

(2)飞思卡尔单片机的功能及特点:MC9S12XS128 是 16 位单片机,由 16 位中央处理单元(CPU12X)、128KB 程序、Flash(P-lash)、8KB RAM、8KB 数据 Flash(D-lash)组成片内存储器。主要功能模块包括:内部存储器,内部 PLL 锁相环模块,2 个异步串口通讯 SCI ,1个串行外设接口 SPI MSCAN 模块,1 个 8 通道输入/输出比较定时器模块 TIM ,周期中断定时器模块 PIT ,16 通道

A/D 转换模块 ADC ,1 个 8 通道脉冲宽度调制模块 PWM ,输入/输出数字 I/O 口。

本次设计中主要用到PORTA,PORTB端口:

PORTA:PORTA 为通用 I/O 口, 共 8 个,作为通用数字 I/O 口使用,未集成特殊功能.主要配置寄存器有:数据寄存器 PORTA、数据方向寄存 DDRA、上拉电阻控制寄存器PUCR 和驱动控制寄存器 RDR。 a. 数据寄存器 PORTA

通过写 1/0 使单片机对应引脚输出高低电平,或通过读取数据寄存器获得对应引脚的高低电平值。例:PORTA_PB0=1 b. 数据方向寄存器 DDRA

DDRA 寄存器配置引脚为输出口还是输入口,“0”,输入口;“1”,输出口。MCU 复位后,DDRA 值为 0x00, 引脚默认为输入口。例:DDRA=0xFF //配置 PORTA 口为输出

PORTB:PORTB 为通用数字 I/O 口, 共 8 个。其使用与 PORTA 基本一样。主要配置寄存器有:数据寄存器 PORTB、数据方向寄存 DDRB。上拉电阻控制寄存器 PUCR 和驱动控制寄存器 RDR 与 PORTA 、PORTB、PORTE、PORTK 共用。

a.数据寄存器 PORTB

b.数据方向寄存器 DDRB

四、原理图:

器件说明:OLED液晶显示器(8管脚), 4个1k电阻,4个按键,飞思卡尔芯

片(64管脚)

管脚连接:

GND VCC D0 D1 RST DC GND VCC PB4 PB3 PB1 PB2 FMQ KEY PA1 PA2 PA3 PA4 AN07 MOSI0 PA1 PA2 PA3 PA4 五、流程图 开始显示 开启显示 复位SSD1306 驱动IC初始代码 清0显存 六、程序设计 1.void pll_set(void):内部锁相环模块,单片机使用PLL功能能够获得更高的总线频率,这对于需要提高单片机运行速度的应用场合非常必要。 2.void OLED_Init(void):初始化OLED液晶显示屏 3.void LCD_WrCmd(byte cmd):写指令函数 4.void LCD_WrDat(byte data):写数据函数 5.void LCD_PutPixel(byte x,byte y):填充一个点 6.void LCD_P6x8Str(byte x,byte y,byte ch[]):显示字符串函数 7.void main(void):主函数 #include \"main.h\" //所有头文件已包含在在include.h里 unsigned char ch_data[]=\" ---By tangxuqing\"; //显示数组 /*

******************************************************************* *

* 延时函数 *

******************************************************************** */

void delayms(unsigned long ms) {

unsigned int ii,jj; if(ms<1) ms=1;

for(ii=0;iifor(jj=0;jj<3338*2;jj++); //80MHz--1ms } /*

******************************************************************* *

* 时钟设置

* 通过锁相环(PLL)设置系统时钟为56M *

******************************************************************** */

void pll_set(void) {

CLKSEL=0X00; PLLCTL_PLLON=1;

SYNR =0xc0 | 0x06; REFDV=0x80 | 0x01; POSTDIV=0x00; _asm(nop); _asm(nop); _asm(nop); _asm(nop);

while(!(CRGFLG_LOCK==1)); CLKSEL_PLLSEL =1; } /*

******************************************************************* *

* 对I/O口的初定义

* *

******************************************************************** */

void init_IO(void) {

DDRA = 0xff; PORTA = 0xfb; } /*

******************************************************************* *

* 主函数 * *

******************************************************************** */

void main(void) {

/* put your own code here */

_DISABLE_COP(); //关看门狗 DisableInterrupts; //关中断

pll_set(); //锁相环初始化56MHz

uart_init(); //串口初始化(中断,9600) OLED_Init(); //OLED初始化 sound_init(); //声音初始化

init_IO(); //通用I/O口初始化

LCD_P6x8Str(1,6,ch_data); //显示开机界面 kaiji_fmq();//开机声音 DDRA_DDRA1 = 0; DDRA_DDRA2 = 0; DDRA_DDRA3 = 0;

DDRA_DDRA4 = 0; //SET PORTA I/O INPUT

PORTAB_PA1 = 1; PORTAB_PA2 = 1; PORTAB_PA3 = 1; PORTAB_PA4 = 1; EnableInterrupts;

for(;;) {

//_FEED_COP(); /* feeds the dog */

/* for(i=0;i<32;i++){ //扫描显示点 for(j=0;j<128;j++) LCD_PutPixel(j,i); delayms(1); } */

// LCD_P6x8Str(0,0,ch_data); if(!PORTA_PA1){

LCD_P6x8Str(1,2,\"1\");

}

if(!PORTA_PA2){

LCD_P6x8Str(1,3,\"2\");

}

if(!PORTA_PA3){

LCD_P6x8Str(1,4,\"3\");

}

if(!PORTA_PA4){

LCD_P6x8Str(1,5,\"4\");

}

} /* loop forever */

/* please make sure that you never leave main */ }

OLED.c函数(子程序函数)

#define OLED_GLO #include \"oled.h\"

#define XLevelL 0x00 #define XLevelH 0x10

#define XLevel ((XLevelH&0x0F)*16+XLevelL) #define Max_Column 128 #define Max_Row 64

#define Brightness 0xCF /*

4线SPI使用说明:

VBT 供内部DC-DC电压,3.3~4.3V,如果使用5V电压,为保险起见串一个100~500欧的电阻

VCC 供内部逻辑电压 1.8~6V GND 地

BS0 低电平 BS1 低电平 BS2 低电平

CS 片选管脚

DC 命令数据选择管脚 RES 模块复位管脚 D0(SCLK),时钟脚,由MCU控制 D1(MOSI),主输出从输入数据脚,由MCU控制

D2 悬空

D3-D7 ,低电平,也可悬空,但最好设为低电平 RD 低电平,也可悬空,但最好设为低电平 RW 低电平,也可悬空,但最好设为低电平 RD 低电平,也可悬空,但最好设为低电平 C7---D0(SCLK)时钟脚,由MCU控制

C6---D1(MOSI)主输出从输入数据脚,由MCU控制 C0---RST 模块复位管脚

C4---DC 命令数据选择管脚*/

/**************************** 引脚定义 *********************************** PB1 RST PB2 DC PB3 D1 PB4 D0

*************************************************************************/ #define X_WIDTH 128 #define Y_WIDTH 64

//====================================== const byte F6x8[][6] = {

{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // \" { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '

{ 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // : // ; // < // = // > // ? // @ // A // B // C // D // E // F // G // H // I // J // K // L // M // N // O // P // Q // R // S

{ 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55 { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },// ' {0x00, 0x88, 0x48, 0x28, 0x18, 0xff }, //a {0x00, 0xff, 0xa0, 0x90, 0x88, 0xe4 }, //b {0x00, 0x02, 0x82, 0x7A, 0x2A, 0xEA }, // c {0x2B, 0x7a, 0x82, 0x02, 0x02, 0x00 }, // d {0x00, 0x7C, 0x54, 0x54, 0x54, 0x00 }, // e {0xFE, 0x02, 0x22, 0x3E, 0x00, 0x00 }, // f {0x00, 0xFF, 0x05, 0x75, 0x15, 0xFD }, // g {0x15, 0x75, 0x07, 0x38, 0x80, 0xFF }, // h {0x00, 0x06, 0x02, 0x23, 0xAA, 0xFB }, // i {0x2A, 0x23, 0x02, 0x06, 0x00, 0x00 }, // j {0xFE, 0x22, 0x3E, 0x00, 0x06, 0x12 }, // k {0x7A, 0x1B, 0x7A, 0x52, 0x66, 0x00 }, // l //{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a //{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b //{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c //{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d //{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e //{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f //{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g //{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h //{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i //{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j //{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k //{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s

{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z

{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } // horiz lines }; /*

A13---D0(SCLK)时钟脚,由MCU控制 13

A12---D1(MOSI)主输出从输入数据脚,由MCU控制 12 A15---RST 模块复位管脚 15

A14---DC 命令数据选择管脚 14*/ void OLED_Init(void) {

DDRB=DDRB|0x1e; DCHIGH(); CLKHIGH(); RESLOW(); LCD_DLY_ms(50); RESHIGH();

LCD_WrCmd(0xae);//--turn off oled panel

LCD_WrCmd(0x00);//---set low column address LCD_WrCmd(0x10);//---set high column address

LCD_WrCmd(0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)

LCD_WrCmd(0x81);//--set contrast control register

LCD_WrCmd(0xcf); // Set SEG Output Current Brightness

LCD_WrCmd(0xa1);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 LCD_WrCmd(0xc8);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 // LCD_WrCmd(0xa0);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 // LCD_WrCmd(0xc0);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 LCD_WrCmd(0xa6);//--set normal display

LCD_WrCmd(0xa8);//--set multiplex ratio(1 to 64) LCD_WrCmd(0x3f);//--1/64 duty

LCD_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) LCD_WrCmd(0x00);//-not offset

LCD_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency LCD_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec LCD_WrCmd(0xd9);//--set pre-charge period

LCD_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock LCD_WrCmd(0xda);//--set com pins hardware configuration LCD_WrCmd(0x12);

LCD_WrCmd(0xdb);//--set vcomh

LCD_WrCmd(0x40);//Set VCOM Deselect Level

LCD_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02) LCD_WrCmd(0x02);//

LCD_WrCmd(0x8d);//--set Charge Pump enable/disable LCD_WrCmd(0x14);//--set(0x10) disable

LCD_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5) LCD_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7) LCD_WrCmd(0xaf);//--turn on oled panel OLCD_Fill(0); //初始清屏 LCD_Set_Pos(0,0); //DZXH_LOGO(); } /*

A26---D0(SCLK)时钟脚,由MCU控制 13

A27---D1(MOSI)主输出从输入数据脚,由MCU控制 12 A24---RST 模块复位管脚 15

A25---DC 命令数据选择管脚 14*/ void LCD_WrDat(byte data) { byte i=8; //LCD_CS=0;; DCHIGH();;;;//DC=1 ;;// NOP();

CLKLOW();;;;//D0=0 ;;//NOP(); while(i--) {

if(data&0x80) {MISOHIGH();;;;}//D1=1 else {MISOLOW();;;;}//D1==0 CLKHIGH();//D0=1 ;;//NOP();;;;; //asm(\"nop\");

CLKLOW();;;;;//D0==0 data<<=1; } //LCD_CS=1; }

void Dis_Num(byte y, byte x, unsigned int num,byte N) {

// byte line; byte j=0;

byte n[6]={0}; x=x*8;

n[0]=(num/10000)%10; n[1]=(num/1000)%10; n[2]=(num/100)%10; n[3]=(num/10)%10; n[4]=num%10; // n[6]='\\0';

for(j=0;j<5;j++) n[j]=n[j]+16+32;

LCD_P6x8Str(x,y,&n[5-N]);//从ACSII码表中读取字节,然后写入液晶 } /*

A26---D0(SCLK)时钟脚,由MCU控制 E4

A27---D1(MOSI)主输出从输入数据脚,由MCU控制 E3 A24---RST 模块复位管脚 E6

A25---DC 命令数据选择管脚 E5 */ void LCD_WrCmd(byte cmd) { byte i=8; //LCD_CS=0;; DCLOW();;;;; CLKLOW();;;;; //asm(\"nop\");

while(i--) {

if(cmd&0x80) {MISOHIGH();;;;;} else {MISOLOW();;;;;;} CLKHIGH();;;;; ;;;;;;;;//NOP();;;;; //asm(\"nop\");

CLKLOW();;;;; cmd<<=1;;;;; } //LCD_CS=1; }

void LCD_Set_Pos(byte x, byte y) {

LCD_WrCmd(0xb0+y);

LCD_WrCmd(((x&0xf0)>>4)|0x10);

LCD_WrCmd(x&0x0f);//|0x01);原来的版本图像整体右移一列,导致低128列移到第一列显示,不知道这么做是为什么,暂时先改回来 }

void OLCD_Fill(byte bmp_data) { byte y,x; for(y=0;y<8;y++) { LCD_WrCmd(0xb0+y); LCD_WrCmd(0x01); LCD_WrCmd(0x10); for(x=0;xvoid LCD_CLS(void) { byte y,x; for(y=0;y<8;y++) { LCD_WrCmd(0xb0+y); LCD_WrCmd(0x01); LCD_WrCmd(0x10); for(x=0;xvoid LCD_DLY_ms(uint16 ms) {

word a; while(ms) {

a=2350; while(a--); ms--; }

return; }

//============================================================== //函数名: void LCD_PutPixel(byte x,byte y) //功能描述:绘制一个点(x,y)

//参数:真实坐标值(x,y),x的范围0~127,y的范围0~64 //返回:无

//============================================================== void LCD_PutPixel(byte x,byte y) { byte data1; //data1当前点的数据

LCD_Set_Pos(x,y); data1 = 0x01<<(y%8); LCD_WrCmd(0xb0+(y>>3)); LCD_WrCmd(((x&0xf0)>>4)|0x10); LCD_WrCmd((x&0x0f)|0x00); LCD_WrDat(data1); }

//============================================================== //函数名: void LCD_Rectangle(byte x1,byte y1,

// byte x2,byte y2,byte color,byte gif) //功能描述:绘制一个实心矩形

//参数:左上角坐标(x1,y1),右下角坐标(x2,y2)

// 其中x1、x2的范围0~127,y1,y2的范围0~63,即真实坐标值 //返回:无

//============================================================== void LCD_Rectangle(byte x1,byte y1,byte x2,byte y2,byte gif) { byte n; LCD_Set_Pos(x1,y1>>3); for(n=x1;n<=x2;n++) { LCD_WrDat(0x01<<(y1%8)); if(gif == 1) LCD_DLY_ms(50);

} LCD_Set_Pos(x1,y2>>3); for(n=x1;n<=x2;n++) { LCD_WrDat(0x01<<(y2%8)); if(gif == 1) LCD_DLY_ms(5); } }

//============================================================== //函数名:LCD_P6x8Str(byte x,byte y,byte *p) //功能描述:写入一组标准ASCII字符串 //参数:显示的位置(x,y),y为页范围0~7,要显示的字符串 //返回:无

//============================================================== void LCD_P6x8Str(byte x,byte y,byte ch[]) {

byte c=0,i=0,j=0; while (ch[j]!='\\0') {

c =ch[j]-32;

if(x>126){x=0;y++;} LCD_Set_Pos(x,y); for(i=0;i<6;i++) LCD_WrDat(F6x8[c][i]); x+=6; j++; } }

//============================================================== //函数名: void Draw_BMP(byte x,byte y) //功能描述:显示BMP图片128×64

//参数:起始点坐标(x,y),x的范围0~127,y为页的范围0~7 //返回:无

//============================================================== void Draw_BMP(byte x0,byte y0,byte x1,byte y1,byte *bmp) {

// word ii=0; byte x,y;

if(y1%8==0) y=y1/8;

else

y=y1/8+1;

for(y=y0;y<=y1;y++) {

LCD_Set_Pos(x0,y); for(x=x0;x<=x1;x++) {

LCD_WrDat(*bmp++); } } }

void Draw_BMP2(byte x0,byte y0,byte x1,byte y1,byte *bmp) {

// word ii=0; byte x,y;

if(y1%8==0) y=y1/8; else

y=y1/8+1;

for(y=y0;y<=y1;y+=2) {

LCD_Set_Pos(x0,y); for(x=x0;x<=x1;x++) {if((*bmp+=3)>0x80) LCD_WrDat(0x01); else LCD_WrDat(0x00); } } }

void LED_PrintImage(byte *pucTable, uint16 usRowNum, uint16 usColumnNum) {

byte ucData; word i,j,k,m,n; word usRowTmp;

m = usRowNum >> 3; //计算图片行数以8位为一组完整的组数 n = usRowNum % 8; //计算分完组后剩下的行数

for(i = 0; i < m; i++) //完整组行扫描

{

LCD_Set_Pos(0,(uint8)i);

usRowTmp = i << 3; //计算当前所在行的下标 for(j = 0; j < usColumnNum; j++) //列扫描 {

ucData = 0;

for(k = 0; k < 8; k++) //在i组中对这8行扫描 {

ucData = ucData >> 1;

if((pucTable + (usRowTmp + k) * usColumnNum)[j] == 0) {

ucData = ucData | 0x80; }

}

LCD_WrDat(ucData); } }

LCD_Set_Pos(0,(uint8)i); //设置剩下的行显示的起始坐标 usRowTmp = i << 3; //计算当前所在行的下标 for(j = 0; j < usColumnNum; j++) //列扫描 {

ucData = 0;

for(k = 0; k < n; k++) //对剩下的行扫描 {

ucData = ucData >> 1;

if((pucTable + (usRowTmp + k) * usColumnNum)[j] == 0) {

ucData = ucData | 0x80; }

}

ucData = ucData >> (8 - n); LCD_WrDat(ucData); }

return; }

七、调试过程

(1)使用Altium画出电路图:在电路图设计过程中,注明所用器件名称,

规格,注意管脚的连接,尽可能让电路原理图规范,正确,方便看图焊接的工作。

(2)测量电路焊接是否正常:焊接好电路板后,首先用万用表测试是否

连通,将表笔两端分别置于连接的两管脚,将万用表开关置于分贝档,若有响声,则电路已经联通,分别测试该设计所用的所有管脚。

(3)检验输入I0:用万用表分别检测4个按键,看按键是否起到输入作用。

将万用表开关置于电压档,分别测试按键按下前后的单片机电压。若按键前电压为5v,按键后为0,则说明按键起到了输入的作用。

(4)输出IO端口:输出口主要检验OLED的显示情况,首先用万用表测试,

检查OLED管脚链接是否有问题。

(5)程序:程序中主要注意OLED显示部分,因为OLED相对于单片机速度比较慢,所以在编写程序时应注意加延时。

八、附:图片截屏

图1.使用FreescaleCodeWarrior软件编写程序

图2.使用BDM仿真器下载程序

图3.硬件电路板设计:

九、遇到的问题与解决的办法

1)、在焊接电路上,由于导线的接触不良,而导致电路不畅通。后经过万能电表的检测,找到了问题所在,并及时解决了问题。 2)、因为oled液晶显示器上的按键不方便操作显示。为了解决这个问题,只能在外部接入四个按键,才让显示更为方便。

4)、本程序使用的是低电平有效,由于粗心的问题,导致液晶屏无法显示数字,后来通过修改程序才解决了这个问题。

5)、高低电平哪一个输出的有效的判断上,出现了一定的问题。经过仔细读看程序,找到了问题的根源所在,并且及时的解决了问题。 6)、由于坐标的定位错误,导致数字的显示出现模糊不清,错位等问题。后通过细心检测和计算,成功的解决了该问题。

十、心得体会

通过本次实习,使我对OLED液晶显示屏及飞思卡尔单片机的应用都有了很深的理解,这是第一次独立的把软件及硬件相结合,包括改写程序及焊接电路板,整个过程中也有不成功的时候,经过不断修改检验,最终了成功的完成本次的实习项目,使我对软件及硬件设计上有了更加浓厚的兴趣,同时也增长了不少经验。

因篇幅问题不能全部显示,请点此查看更多更全内容