#include "oled.h" #include "stm32f10x_spi.h" #include "sysport.h" /******************************************************************************** * @file oled.c * @author 晏诚科技 Mr.Wang * @version V1.0.0 * @date 11-Dec-2018 * @brief 提供1.3英寸OLED显示屏相关驱动。 ****************************************************************************** * @attention 1.3英寸显示屏的像素为横向128 纵向64。如果显示大小:12*6的数字/字符一行最多显示 * 16个字符。 *******************************************************************************/ /************************************************************************************************** * 名 称: void OLED_Init(void) * 功能说明: 初始化SSD1306 ***************************************************************************************************/ void delay(void) { u8 t=3; while(t--); } void OLED_Init(void) { /* 配置IO */ Gpio_Init(OLED_CS_PORT, OLED_CS_PIN, GPIO_Mode_Out_PP) ; //SPI NSS io口配置 Gpio_Init(OLED_SCLK_PORT, OLED_SCLK_PIN, GPIO_Mode_Out_PP) ; //SPI SCLK io口配置 Gpio_Init(OLED_MISO_PORT, OLED_MISO_PIN, GPIO_Mode_Out_PP) ; //SPI MISO io口配置 Gpio_Init(OLED_MOSI_PORT, OLED_MOSI_PIN, GPIO_Mode_Out_PP) ; //SPI MOSI io口配置 Gpio_Init(OLED_RST_PORT, OLED_RST_PIN , GPIO_Mode_Out_PP) ; //OLED RST io口配置 //SPIxBoardInit() ; OLED_RST_SET() ; Wait_For_Nms(100) ; OLED_RST_CLR() ; Wait_For_Nms(100) ; OLED_RST_SET() ; OledWriteByte(0xAE, OLED_CMD, false) ; //--turn off oled panel OledWriteByte(0x02, OLED_CMD, false) ; //---set low column address OledWriteByte(0x10, OLED_CMD, false) ; //---set high column address OledWriteByte(0x40, OLED_CMD, false) ; //--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) OledWriteByte(0x81, OLED_CMD, false) ; //--set contrast control register OledWriteByte(OLED_BRIGHTNESS, OLED_CMD, false) ; // Set SEG Output Current Brightness OledWriteByte(0xA1, OLED_CMD, false) ; //--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 OledWriteByte(0xC8, OLED_CMD, false) ; //Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 OledWriteByte(0xA6, OLED_CMD, false) ; //--set normal display OledWriteByte(0xA8, OLED_CMD, false) ; //--set multiplex ratio(1 to 64) OledWriteByte(0x3f, OLED_CMD, false) ; //--1/64 duty OledWriteByte(0xD3, OLED_CMD, false) ; //-set display offset Shift Mapping RAM Counter (0x00~0x3F) OledWriteByte(0x00, OLED_CMD, false) ; //-not offset OledWriteByte(0xd5, OLED_CMD, false) ; //--set display clock divide ratio/oscillator frequency OledWriteByte(0x80, OLED_CMD, false) ; //--set divide ratio, Set Clock as 100 Frames/Sec OledWriteByte(0xD9, OLED_CMD, false) ; //--set pre-charge period OledWriteByte(0xF1, OLED_CMD, false) ; //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OledWriteByte(0xDA, OLED_CMD, false) ; //--set com pins hardware configuration OledWriteByte(0x12, OLED_CMD, false) ; OledWriteByte(0xDB, OLED_CMD, false) ; //--set vcomh OledWriteByte(0x40, OLED_CMD, false) ; //Set VCOM Deselect Level OledWriteByte(0x20, OLED_CMD, false) ; //-Set Page Addressing Mode (0x00/0x01/0x02) OledWriteByte(0x02, OLED_CMD, false) ; // OledWriteByte(0x8D, OLED_CMD, false) ; //--set Charge Pump enable/disable OledWriteByte(0x14, OLED_CMD, false) ; //--set(0x10) disable OledWriteByte(0xA4, OLED_CMD, false) ; // Disable Entire Display On (0xa4/0xa5) OledWriteByte(0xA6, OLED_CMD, false) ; // Disable Inverse Display On (0xa6/a7) OledWriteByte(0xAF, OLED_CMD, false) ; //--turn on oled panel OledWriteByte(0xAF, OLED_CMD, false) ; //display ON OledClear() ; //清除显示屏 OledSetPos(0, 0) ; //设置显示光标位置 // OledPrintf(LINE_MID, HIGH_16, LINE1, false, "晏 诚 科 技") ; //第一行居中显示“晏 诚 科 技” } /************************************************************************************************** * 名 称: void OledPrintf(ALINEMODE_e eMode, OLEDLINE_e line, char *format, ...) * 功能说明: OLED显示屏line行按照eMode对齐模式显示可变长字符串 * 入口参数: * @param1 eMode: ALINEMODE_e枚举类型,表示行显示的对齐方式 * @param2 CHARHIGH_e high: CHARHIGH_e结构体,表示字符高度 * @param3 line: OLEDLINE_e枚举类型,表示内容显示在哪一行 * @param4 char *format: 可变参数格式 * @param5 ... : 可变参数 * 注 意: 1、该函数只能显示汉字高为16的字符,如果需要显示其他高度的字符需要修改字符码表。 * 2、单行显示字符长度大于X_MAX_WIDTH/high*2,则只显示X_MAX_WIDTH/high*2长度字符,多余字符不显示 *************************************************************************************************/ void OledPrintf(ALINEMODE_e eMode, CHARHIGH_e high, OLEDLINE_e line, bool reverse, char *format, ...) { unsigned int x = 0, i, k, t, y, lineMaxChar = X_MAX_WIDTH/(high/2), n ; if( high == HIGH_16 ) { y = line*2 ; n = (sizeof(sCN16_Msk)/sizeof(FNTGBK16_s)) ; } else { y = line*2 ; n = (sizeof(sCN12_Msk)/sizeof(FNTGBK12_s)) ; } va_list ap; //ap指向参数的地址 va_start (ap, format); //让ap指针指向可变参数表里的第一个参数 char *buf = portMalloc(lineMaxChar+1) ; int outLen = vsnprintf(buf, lineMaxChar+1, (const char*)format, ap); if( (outLen > lineMaxChar) && (*(buf+lineMaxChar-1) > 127)) /*如果单行显示字符长度大于LINE_MAX_CHAR,则只显示LINE_MAX_CHAR长度字符,多余字符不显示&&最后一个字符为汉字*/ outLen = lineMaxChar-1 ; else if((outLen > lineMaxChar) ) /*如果单行显示字符长度大于LINE_MAX_CHAR,则只显示LINE_MAX_CHAR长度字符,多余字符不显示*/ outLen = lineMaxChar ; switch( eMode ) { case LINE_MID : { x = (high/2)*((lineMaxChar - outLen)/2) ; break ; } case LINE_RIGHT: { x = (high/2)*(lineMaxChar - outLen) ; break ; } default: { x = 0 ; break ; } } if(outLen > 0 ) /*vsnprintf执行OK*/ { OledClearLine(line) ; for(k=0; k 127) /*大于127,为汉字,前后两个组成汉字内码*/ { for(i=0; i>4)|0x10, OLED_CMD, false); OledWriteByte(((x+2)&0x0f), OLED_CMD, false); } /************************************************************************************************** * 名 称: void OledDisplayOn(void) * 功能说明: 开启OLED显示 ***************************************************************************************************/ void OledDisplayOn(void) { OledWriteByte(0X8D, OLED_CMD, false) ; //SET DCDC命令 OledWriteByte(0X14, OLED_CMD, false) ; //DCDC ON OledWriteByte(0XAF, OLED_CMD, false) ; //DISPLAY ON } /************************************************************************************************** * 名 称: void OledDisplayOff(void) * 功能说明: 关闭OLED显示 ***************************************************************************************************/ void OledDisplayOff(void) { OledWriteByte(0X8D, OLED_CMD, false) ; //SET DCDC命令 OledWriteByte(0X10, OLED_CMD, false) ; //DCDC OFF OledWriteByte(0XAE, OLED_CMD, false) ; //DISPLAY OFF } /************************************************************************************************** * 名 称: void OledClear(void) * 功能说明: 关闭OLED显示 * 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! ***************************************************************************************************/ void OledClear(void) { unsigned char i, n ; for(i=0; i<8; i++) { OledWriteByte (0xb0+i, OLED_CMD, false); //设置页地址(0~7) OledWriteByte (0x02, OLED_CMD, false); //设置显示位置—列低地址 OledWriteByte (0x10, OLED_CMD, false); //设置显示位置—列高地址 for(n=0; n < 128; n++) { OledWriteByte(0, OLED_DATA, false); } } //更新显示 } /************************************************************************************************** * 名 称: void OledClearLine(OLEDLINE_e line) * 功能说明: 清空显示屏第line行的内容 ***************************************************************************************************/ void OledClearLine(OLEDLINE_e line) { OLED_ShowString(0, line*2, false, (char *)" ", HIGH_16); } /************************************************************************************************** * 名 称: void OledWriteByte(char dat, char cmd, bool reserse) * 功能说明: 向SSD1106写入一个字节。 * 入口参数: * @param1 char dat: 写入的数据 * @param2 char cmd: 数据/命令标志 0,表示命令;1,表示数据; * @param3 bool reserse: 写入数据是否“反白”显示 *************************************************************************************************/ void OledWriteByte(char dat, char cmd, bool reserse) { char i = 0 ; if(cmd == OLED_DATA) //写入数据 { OLED_MISO_SET() ; } else //写入命令 { reserse = false ; //写入命令不存在 反白 OLED_MISO_CLR() ; } OLED_CS_CLR() ; for(i=0; i<8; i++) { OLED_SCLK_CLR(); if(reserse == false) { if( (dat & 0x80) ) { OLED_MOSI_SET() ; } else { OLED_MOSI_CLR() ; } } else { if( (dat & 0x80) ) { OLED_MOSI_CLR() ; } else { OLED_MOSI_SET() ; } } OLED_SCLK_SET() ; delay(); dat <<= 1 ; } OLED_CS_SET(); OLED_MISO_SET(); } /************************************************************************************************** * 名 称: OledShowChar(char x, char y, CHARHIGH_e high, bool reverse, char chr) * 功能说明: 在(x,y)坐标位置显示一个字符 * 入口参数: * @param1 char x: 横向坐标(0~127) * @param2 char y: 纵向坐标(0~63) * @param3 char chr: 需要显示的字符 * @param4 CHARHIGH_e high: CHARHIGH_e结构体,表示字符高度 ***************************************************************************************************/ void OledShowChar(char x, char y, CHARHIGH_e high, bool reverse, char chr) { char c = 0, i = 0 ; c = chr - ' ' ; //得到偏移后的值 if( x > (X_MAX_WIDTH-1) ) /*如果横向坐标大于最大像素宽度X_MAX_WIDTH,执行换行操作*/ { x = 0 ; y = y+2 ; } switch( high ) { case HIGH_12: /*显示的字符高度为12*/ { OledSetPos(x, y+1) ; for(i=0; i<6; i++) { OledWriteByte(ASCII_HIGH12[c][i], OLED_DATA, reverse) ; } break ; } case HIGH_16: /*显示的字符高度为16*/ { OledSetPos(x, y) ; //设置起始坐标 for(i=0; i<8; i++) { OledWriteByte(ASCII_HIGH16[c][i], OLED_DATA, reverse) ; //显示16字高的上半部分 } OledSetPos(x, y+1) ; for(i=0; i<8; i++) { OledWriteByte(ASCII_HIGH16[c][i+8], OLED_DATA, reverse) ; //显示16字高的下半部分 } break ; } default: { ErrorLogPrintf("No CHARHIGH_e .") ; break ; } } } /************************************************************************************************** * 名 称: void OledShowChar(char x,char y,char *chr) * 功能说明: 在(x,y)坐标位置显示一个字符串 * 入口参数: * @param1 char x: 横向坐标(0~127) * @param2 char y: 纵向坐标(0~63) * @param3 char *chr: 需要显示的字符串指针 * @param4 CHARHIGH_e high: CHARHIGH_e结构体,表示字符高度 ***************************************************************************************************/ void OLED_ShowString(char x, char y, bool reverse, char *chr, CHARHIGH_e high) { char j = 0 ; while(*(chr+j) != '\0') /*单字节轮询查找直到遇到字符串结尾标识符*/ { OledShowChar(x, y, high, reverse, *(chr+j)) ; //显示字符串 x += high/2 ; //横坐标偏移high/2像素 if( x > 120 ) //横坐标大于120,余下部分不足以显示一个字符时,操作换行 { x = 0 ; y += 1 ; // SysErr("OLED_ShowString") ; } j++ ; } } /************************************************************************************************** * 名 称: void OledShowCHinese(char x, char y, const char *buf, CHARHIGH_e high) * 功能说明: 在(x,y)坐标位置显示一个汉子 * 入口参数: * @param1 char x: 横向坐标(0~127) * @param1 char y: 横向坐标(0~63) * @param2 char *buf: 汉字数组 * @param4 CHARHIGH_e high: CHARHIGH_e结构体,表示字符高度 ***************************************************************************************************/ void OledShowCHinese(char x, char y, bool reverse, const char *buf, CHARHIGH_e high) { char t = 0; unsigned int k = 0 ; OledSetPos(x, y) ; //设置坐标 switch( high ) { case HIGH_12: { for(k=0; k