[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
* 模块名称 : OLED显示器驱动模块
* 文件名称 : bsp_oled.c
* 版 本 : V1.1
* 说 明 : OLED 屏(128x64)底层驱动程序,驱动芯片型号为 SSD1306. 本驱动程序适合于STM32-V5开发板.
* OLED模块挂在FSMC总线上。
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2013-02-01 armfly 正式发布
* V1.1 2015-10-14 armfly 添加24点阵,32点阵汉字和ASCII支持
*
* Copyright (C), 2015-2020, 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "fonts.h"
/*
安富莱STM32-V6开发板的OLED显示接口为FSMC总线模式。
*/
/* 下面2个宏任选 1个; 表示显示方向 */
#define DIR_NORMAL /* 此行表示正常显示方向 */
//#define DIR_180 /* 此行表示翻转180度 */
#ifdef OLED_SPI3_EN
/*
SPI 模式接线定义 (只需要6根杜邦线连接) 本例子采用软件模拟SPI时序
【OLED模块排针】 【开发板TFT接口(STM32口线)】
VCC ----------- 3.3V
GND ----------- GND
CS ----------- TP_NCS (PI10)
RST ----------- NRESET (也可以不连接)
D0/SCK ----------- TP_SCK (PB3)
D1/SDIN ----------- TP_MOSI (PB5)
*/
#define RCC_OLED_PORT (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI) /* GPIO端口时钟 */
#define OLED_CS_PORT GPIOI
#define OLED_CS_PIN GPIO_PIN_10
#define OLED_SCK_PORT GPIOB
#define OLED_SCK_PIN GPIO_PIN_3
#define OLED_SDIN_PORT GPIOB
#define OLED_SDIN_PIN GPIO_PIN_5
/* 定义IO = 1和 0的代码 (不用更改) */
#define SSD_CS_1() OLED_CS_PORT->BSRRL = OLED_CS_PIN
#define SSD_CS_0() OLED_CS_PORT->BSRRH = OLED_CS_PIN
#define SSD_SCK_1() OLED_SCK_PORT->BSRRL = OLED_SCK_PIN
#define SSD_SCK_0() OLED_SCK_PORT->BSRRH = OLED_SCK_PIN
#define SSD_SDIN_1() OLED_SDIN_PORT->BSRRL = OLED_SDIN_PIN
#define SSD_SDIN_0() OLED_SDIN_PORT->BSRRH = OLED_SDIN_PIN
#else
/* 定义LCD驱动器的访问地址
TFT接口中的RS引脚连接FSMC_A0引脚,由于是16bit模式,RS对应A1地址线,因此
OLED_RAM的地址是+2
*/
#define OLED_BASE ((uint32_t)(0x60000000))
#define OLED_CMD *(__IO uint16_t *)(OLED_BASE)
#define OLED_DATA *(__IO uint16_t *)(OLED_BASE + (1 << 2)) /* FSMC_A0接D/C, 总线配置为32bit(兼容74HC574端口) */
/*
1.安富莱OLED模块 80XX 模式接线定义 (需要15根杜邦线连接)
【OLED模块排针】 【开发板TFT接口(STM32口线)】
VCC ----------- 3.3V
GND ----------- GND
CS ----------- NCS
RST ----------- NRESET (也可以不连接)
D/C ----------- RS (FSMC_A18)
WE ----------- NWE (FSMC_NWE)
OE ----------- NOE (FSMC_NOE)
D0/SCK ----------- DB0 (FSMC_D0)
D1/SDIN ----------- DB1 (FSMC_D1)
D2 ----------- DB2 (FSMC_D2)
D3 ----------- DB3 (FSMC_D3)
D4 ----------- DB4 (FSMC_D4)
D5 ----------- DB5 (FSMC_D5)
D6 ----------- DB6 (FSMC_D6)
D7 ----------- DB7 (FSMC_D7)
*/
#endif
/* 12864 OLED的显存镜像,占用1K字节. 共8行,每行128像素 */
static uint8_t s_ucGRAM[8][128];
/* 为了避免刷屏拉幕感太强,引入刷屏标志。
0 表示显示函数只改写缓冲区,不写屏。1 表示直接写屏(同时写缓冲区) */
static uint8_t s_ucUpdateEn = 1;
static void OLED_ConfigGPIO(void);
static void OLED_WriteCmd(uint8_t _ucCmd);
static void OLED_WriteData(uint8_t _ucData);
static void OLED_BufToPanel(void);
/*
*********************************************************************************************************
* 函 数 名: OLED_InitHard
* 功能说明: 初始化OLED屏
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_InitHard(void)
{
OLED_ConfigGPIO();
/* 上电延迟 */
bsp_DelayMS(50);
/* 模块厂家提供初始化代码 */
OLED_WriteCmd(0xAE); /* 关闭OLED面板显示(休眠) */
OLED_WriteCmd(0x00); /* 设置列地址低4bit */
OLED_WriteCmd(0x10); /* 设置列地址高4bit */
OLED_WriteCmd(0x40); /* 设置起始行地址(低5bit 0-63), 硬件相关*/
OLED_WriteCmd(0x81); /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
OLED_WriteCmd(0xCF); /* 设置对比度参数,缺省CF */
#ifdef DIR_NORMAL
OLED_WriteCmd(0xA0); /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
OLED_WriteCmd(0xC0); /* C0 :正常扫描,从COM0到COM63; C8 : 反向扫描, 从 COM63至 COM0 */
#endif
#ifdef DIR_180
OLED_WriteCmd(0xA1); /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
OLED_WriteCmd(0xC8); /* C0 :正常扫描,从COM0到COM63; C8 : 反向扫描, 从 COM63至 COM0 */
#endif
OLED_WriteCmd(0xA6); /* A6 : 设置正常显示模式; A7 : 设置为反显模式 */
OLED_WriteCmd(0xA8); /* 设置COM路数 */
OLED_WriteCmd(0x3F); /* 1 ->(63+1)路 */
OLED_WriteCmd(0xD3); /* 设置显示偏移(双字节命令)*/
OLED_WriteCmd(0x00); /* 无偏移 */
OLED_WriteCmd(0xD5); /* 设置显示时钟分频系数/振荡频率 */
OLED_WriteCmd(0x80); /* 设置分频系数,高4bit是分频系数,低4bit是振荡频率 */
OLED_WriteCmd(0xD9); /* 设置预充电周期 */
OLED_WriteCmd(0xF1); /* [3:0],PHASE 1; [7:4],PHASE 2; */
OLED_WriteCmd(0xDA); /* 设置COM脚硬件接线方式 */
OLED_WriteCmd(0x12);
OLED_WriteCmd(0xDB); /* 设置 vcomh 电压倍率 */
OLED_WriteCmd(0x40); /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC */
OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用) */
OLED_WriteCmd(0x14); /* 0x14 使能充电泵, 0x10 是关闭 */
OLED_WriteCmd(0xAF); /* 打开OLED面板 */
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DispOn
* 功能说明: 打开显示
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispOn(void)
{
OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用) */
OLED_WriteCmd(0x14); /* 0x14 使能充电泵, 0x10 是关闭 */
OLED_WriteCmd(0xAF); /* 打开OLED面板 */
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DispOff
* 功能说明: 关闭显示
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispOff(void)
{
OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用)*/
OLED_WriteCmd(0x10); /* 0x14 使能充电泵,0x10 是关闭 */
OLED_WriteCmd(0xAE); /* 打开OLED面板 */
}
/*
*********************************************************************************************************
* 函 数 名: OLED_SetDir
* 功能说明: 设置显示方向
* 形 参: _ucDir = 0 表示正常方向,1表示翻转180度
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_SetDir(uint8_t _ucDir)
{
if (_ucDir == 0)
{
OLED_WriteCmd(0xA0); /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
OLED_WriteCmd(0xC0); /* C0 :正常扫描,从COM0到COM63; C8 : 反向扫描, 从 COM63至 COM0 */
}
else
{
OLED_WriteCmd(0xA1); /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
OLED_WriteCmd(0xC8); /* C0 :正常扫描,从COM0到COM63; C8 : 反向扫描, 从 COM63至 COM0 */
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_SetContrast
* 功能说明: 设置对比度
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_SetContrast(uint8_t ucValue)
{
OLED_WriteCmd(0x81); /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
OLED_WriteCmd(ucValue); /* 设置对比度参数,缺省CF */
}
/*
*********************************************************************************************************
* 函 数 名: OLED_StartDraw
* 功能说明: 开始绘图。以后绘图函数只改写缓冲区,不改写面板显存
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_StartDraw(void)
{
s_ucUpdateEn = 0;
}
/*
*********************************************************************************************************
* 函 数 名: OLED_EndDraw
* 功能说明: 结束绘图。缓冲区的数据刷新到面板显存。 OLED_StartDraw() 和 OLED_EndDraw() 必须成对使用
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_EndDraw(void)
{
s_ucUpdateEn = 1;
OLED_BufToPanel();
}
/*
*********************************************************************************************************
* 函 数 名: OLED_ClrScr
* 功能说明: 清屏
* 形 参: _ucMode : 0 表示全黑; 0xFF表示全亮
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_ClrScr(uint8_t _ucMode)
{
uint8_t i,j;
for (i = 0 ; i < 8; i++)
{
for (j = 0 ; j < 128; j++)
{
s_ucGRAM[i][j] = _ucMode;
}
}
if (s_ucUpdateEn == 1)
{
OLED_BufToPanel();
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_BufToPanel
* 功能说明: 将缓冲区中的点阵数据写入面板
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void OLED_BufToPanel(void)
{
uint8_t i,j;
for (i = 0 ; i< 8; i++)
{
OLED_WriteCmd (0xB0 + i); /* 设置页地址(0~7) */
OLED_WriteCmd (0x00); /* 设置列地址的低地址 */
OLED_WriteCmd (0x10); /* 设置列地址的高地址 */
for (j = 0 ; j < 128; j++)
{
OLED_WriteData(s_ucGRAM[i][j]);
}
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DispStr
* 功能说明: 在屏幕指定坐标(左上角为0,0)显示一个字符串
* 形 参:
* _usX : X坐标,对于12864屏,范围为【0 - 127】
* _usY : Y坐标,对于12864屏,范围为【0 - 63】
* _ptr : 字符串指针
* _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont)
{
uint32_t i;
uint8_t code1;
uint8_t code2;
uint32_t address = 0;
uint8_t buf[32 * 32 / 8]; /* 最大支持32点阵汉字 */
uint16_t m;
uint8_t width;
uint8_t font_width,font_height, font_bytes;
uint16_t x, y;
const uint8_t *pAscDot;
uint8_t line_bytes;
uint8_t asc_bytes;
uint8_t hz_bytes;
uint8_t fGT = 0;
#ifdef USE_SMALL_FONT
const uint8_t *pHzDot = g_Hz12;
#else
uint32_t AddrHZK;
#endif
if (_tFont->FontCode == FC_ST_12)
{
font_height = 12;
font_width = 12;
font_bytes = 24;
hz_bytes = 2;
asc_bytes = 1;
fGT = 0;
pAscDot = g_Ascii12;
#ifdef USE_SMALL_FONT
pHzDot = g_Hz12;
#else
AddrHZK = HZK12_ADDR;
#endif
}
else if (_tFont->FontCode == FC_ST_16)
{
/* 缺省是16点阵 */
font_height = 16;
font_width = 16;
font_bytes = 32;
hz_bytes = 2;
asc_bytes = 1;
fGT = 0;
pAscDot = g_Ascii16;
#ifdef USE_SMALL_FONT
pHzDot = g_Hz16;
#else
AddrHZK = HZK16_ADDR;
#endif
}
else if (_tFont->FontCode == FC_ST_24)
{
font_height = 24;
font_width = 24;
font_bytes = 72;
hz_bytes = 3;
asc_bytes = 2;
fGT = 1;
pAscDot = g_Ascii24;
#ifdef USE_SMALL_FONT
pHzDot = g_Hz24;
#else
AddrHZK = HZK24_ADDR;
#endif
}
else // if (_tFont->FontCode == FC_ST_32)
{
font_height = 32;
font_width = 32;
font_bytes = 128;
hz_bytes = 4;
asc_bytes = 2;
fGT = 1;
pAscDot = g_Ascii32;
#ifdef USE_SMALL_FONT
pHzDot = g_Hz32;
#else
AddrHZK = HZK32_ADDR;
#endif
}
/* 开始循环处理字符 */
while (*_ptr != 0)
{
code1 = *_ptr; /* 读取字符串数据, 该数据可能是ascii代码,也可能汉字代码的高字节 */
if (code1 < 0x80)
{
/* 将ascii字符点阵复制到buf */
if (fGT == 1) /* 根据ASCII码搜索点阵 */
{
m = 0;
while(1)
{
address = m * (asc_bytes * font_height + 1);
m++;
if (code1 == pAscDot[address + 0])
{
address += 1;
memcpy(buf, &pAscDot[address], asc_bytes * font_height);
break;
}
else if ((pAscDot[address + 0] == 0xFF) && (pAscDot[address + 1] == 0xFF))
{
/* 字库搜索完毕,未找到,则填充全FF */
memset(buf, 0xFF, font_bytes);
break;
}
}
}
else /* 全ASCII码点阵,直接计算地址 */
{
memcpy(buf, &pAscDot[code1 * (font_bytes / 2)], (font_bytes / 2));
}
width = font_width / 2;
line_bytes = asc_bytes;
}
else
{
code2 = *++_ptr;
if (code2 == 0)
{
break;
}
/* 计算16点阵汉字点阵地址
ADDRESS = [(code1-0xa1) * 94 + (code2-0xa1)] * 32
;
*/
#ifdef USE_SMALL_FONT
m = 0;
while(1)
{
address = m * (font_bytes + 2);
m++;
if ((code1 == pHzDot[address + 0]) && (code2 == pHzDot[address + 1]))
{
address += 2;
memcpy(buf, &pHzDot[address], font_bytes);
break;
}
else if ((pHzDot[address + 0] == 0xFF) && (pHzDot[address + 1] == 0xFF))
{
/* 字库搜索完毕,未找到,则填充全FF */
memset(buf, 0xFF, font_bytes);
break;
}
}
#else /* 用全字库 */
/* 此处需要根据字库文件存放位置进行修改 */
if (code1 >=0xA1 && code1 <= 0xA9 && code2 >=0xA1)
{
address = ((code1 - 0xA1) * 94 + (code2 - 0xA1)) * font_bytes + AddrHZK;
}
else if (code1 >=0xB0 && code1 <= 0xF7 && code2 >=0xA1)
{
address = ((code1 - 0xB0) * 94 + (code2 - 0xA1) + 846) * font_bytes + AddrHZK;
}
memcpy(buf, (const uint8_t *)address, font_bytes);
#endif
width = font_width;
line_bytes = hz_bytes;
}
y = _usY;
/* 开始刷LCD */
for (m = 0; m < font_height; m++) /* 字符高度 */
{
x = _usX;
for (i = 0; i < width; i++) /* 字符宽度 */
{
if ((buf[m * line_bytes + i / 8] & (0x80 >> (i % 8 ))) != 0x00)
{
OLED_PutPixel(x, y, _tFont->FrontColor); /* 设置像素颜色为文字色 */
}
else
{
OLED_PutPixel(x, y, _tFont->BackColor); /* 设置像素颜色为文字背景色 */
}
x++;
}
y++;
}
if (_tFont->Space > 0)
{
/* 如果文字底色按_tFont->usBackColor,并且字间距大于点阵的宽度,那么需要在文字之间填充(暂时未实现) */
}
_usX += width + _tFont->Space; /* 列地址递增 */
_ptr++; /* 指向下一个字符 */
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_PutPixel
* 功能说明: 画1个像素
* 形 参:
* _usX,_usY : 像素坐标
* _ucColor :像素颜色
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_PutPixel(uint16_t _usX, uint16_t _usY, uint8_t _ucColor)
{
uint8_t ucValue;
uint8_t ucPageAddr;
uint8_t ucColAddr;
const uint8_t aOrTab[8] = {0x01, 0x02, 0x04, 0x08,0x10,0x20,0x40,0x80};
const uint8_t aAndTab[8] = {0xFE, 0xFD, 0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F};
ucPageAddr = _usY / 8;
ucColAddr = _usX;
ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
if (_ucColor == 0)
{
ucValue &= aAndTab[_usY % 8];
}
else
{
ucValue |= aOrTab[_usY % 8];
}
s_ucGRAM[ucPageAddr][ucColAddr] = ucValue;
if (s_ucUpdateEn == 1)
{
OLED_WriteCmd (0xB0 + ucPageAddr); /* 设置页地址(0~7) */
OLED_WriteCmd (0x00 + (ucColAddr & 0x0F)); /* 设置列地址的低地址 */
OLED_WriteCmd (0x10 + ((ucColAddr >> 4) & 0x0F)); /* 设置列地址的高地址 */
OLED_WriteData(ucValue);
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_GetPixel
* 功能说明: 读取1个像素
* 形 参:
* _usX,_usY : 像素坐标
* 返 回 值: 颜色值 (0, 1)
*********************************************************************************************************
*/
uint8_t OLED_GetPixel(uint16_t _usX, uint16_t _usY)
{
uint8_t ucValue;
uint8_t ucPageAddr;
uint8_t ucColAddr;
ucPageAddr = _usY / 8;
ucColAddr = _usX;
ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
if (ucValue & (_usY % 8))
{
return 1;
}
else
{
return 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DrawLine
* 功能说明: 采用 Bresenham 算法,在2点间画一条直线。
* 形 参:
* _usX1, _usY1 :起始点坐标
* _usX2, _usY2 :终止点Y坐标
* _ucColor :颜色
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint8_t _ucColor)
{
int32_t dx , dy ;
int32_t tx , ty ;
int32_t inc1 , inc2 ;
int32_t d , iTag ;
int32_t x , y ;
/* 采用 Bresenham 算法,在2点间画一条直线 */
OLED_PutPixel(_usX1 , _usY1 , _ucColor);
/* 如果两点重合,结束后面的动作。*/
if ( _usX1 == _usX2 && _usY1 == _usY2 )
{
return;
}
iTag = 0 ;
/* dx = abs ( _usX2 - _usX1 ); */
if (_usX2 >= _usX1)
{
dx = _usX2 - _usX1;
}
else
{
dx = _usX1 - _usX2;
}
/* dy = abs ( _usY2 - _usY1 ); */
if (_usY2 >= _usY1)
{
dy = _usY2 - _usY1;
}
else
{
dy = _usY1 - _usY2;
}
if ( dx < dy ) /*如果dy为计长方向,则交换纵横坐标。*/
{
uint16_t temp;
iTag = 1 ;
temp = _usX1; _usX1 = _usY1; _usY1 = temp;
temp = _usX2; _usX2 = _usY2; _usY2 = temp;
temp = dx; dx = dy; dy = temp;
}
tx = _usX2 > _usX1 ? 1 : -1 ; /* 确定是增1还是减1 */
ty = _usY2 > _usY1 ? 1 : -1 ;
x = _usX1 ;
y = _usY1 ;
inc1 = 2 * dy ;
inc2 = 2 * ( dy - dx );
d = inc1 - dx ;
while ( x != _usX2 ) /* 循环画点 */
{
if ( d < 0 )
{
d += inc1 ;
}
else
{
y += ty ;
d += inc2 ;
}
if ( iTag )
{
OLED_PutPixel ( y , x , _ucColor) ;
}
else
{
OLED_PutPixel ( x , y , _ucColor) ;
}
x += tx ;
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DrawPoints
* 功能说明: 采用 Bresenham 算法,绘制一组点,并将这些点连接起来。可用于波形显示。
* 形 参:
* x, y :坐标数组
* _ucColor :颜色
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawPoints(uint16_t *x, uint16_t *y, uint16_t _usSize, uint8_t _ucColor)
{
uint16_t i;
for (i = 0 ; i < _usSize - 1; i++)
{
OLED_DrawLine(x[i], y[i], x[i + 1], y[i + 1], _ucColor);
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DrawRect
* 功能说明: 绘制矩形。
* 形 参:
* _usX,_usY:矩形左上角的坐标
* _usHeight :矩形的高度
* _usWidth :矩形的宽度
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawRect(uint16_t _usX, uint16_t _usY, uint8_t _usHeight, uint16_t _usWidth, uint8_t _ucColor)
{
/*
---------------->---
|(_usX,_usY) |
V V _usHeight
| |
---------------->---
_usWidth
*/
OLED_DrawLine(_usX, _usY, _usX + _usWidth - 1, _usY, _ucColor); /* 顶 */
OLED_DrawLine(_usX, _usY + _usHeight - 1, _usX + _usWidth - 1, _usY + _usHeight - 1, _ucColor); /* 底 */
OLED_DrawLine(_usX, _usY, _usX, _usY + _usHeight - 1, _ucColor); /* 左 */
OLED_DrawLine(_usX + _usWidth - 1, _usY, _usX + _usWidth - 1, _usY + _usHeight, _ucColor); /* 右 */
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DrawCircle
* 功能说明: 绘制一个圆,笔宽为1个像素
* 形 参:
* _usX,_usY :圆心的坐标
* _usRadius :圆的半径
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint8_t _ucColor)
{
int32_t D; /* Decision Variable */
uint32_t CurX; /* 当前 X 值 */
uint32_t CurY; /* 当前 Y 值 */
D = 3 - (_usRadius << 1);
CurX = 0;
CurY = _usRadius;
while (CurX <= CurY)
{
OLED_PutPixel(_usX + CurX, _usY + CurY, _ucColor);
OLED_PutPixel(_usX + CurX, _usY - CurY, _ucColor);
OLED_PutPixel(_usX - CurX, _usY + CurY, _ucColor);
OLED_PutPixel(_usX - CurX, _usY - CurY, _ucColor);
OLED_PutPixel(_usX + CurY, _usY + CurX, _ucColor);
OLED_PutPixel(_usX + CurY, _usY - CurX, _ucColor);
OLED_PutPixel(_usX - CurY, _usY + CurX, _ucColor);
OLED_PutPixel(_usX - CurY, _usY - CurX, _ucColor);
if (D < 0)
{
D += (CurX << 2) + 6;
}
else
{
D += ((CurX - CurY) << 2) + 10;
CurY--;
}
CurX++;
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_DrawBMP
* 功能说明: 在LCD上显示一个BMP位图,位图点阵扫描次序:从左到右,从上到下
* 形 参:
* _usX, _usY : 图片的坐标
* _usHeight :图片高度
* _usWidth :图片宽度
* _ptr :单色图片点阵指针,每个像素占用1个字节
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawBMP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint8_t *_ptr)
{
uint16_t x, y;
for (x = 0; x < _usWidth; x++)
{
for (y = 0; y < _usHeight; y++)
{
OLED_PutPixel(_usX + x, _usY + y, *_ptr);
}
}
}
/*
*********************************************************************************************************
* 函 数 名: OLED_ConfigGPIO
* 功能说明: 配置OLED控制口线,设置为8位80XX总线控制模式或SPI模式
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void OLED_ConfigGPIO(void)
{
#ifdef OLED_SPI3_EN
/* 1.配置GPIO,模拟SPI */
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_OLED_PORT, ENABLE); /* 打开GPIO时钟 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /* 设为输出口 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 设为推挽输出模式 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* 上下拉电阻不使能 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; /* IO口最大速度 */
GPIO_InitStructure.GPIO_Pin = OLED_CS_PIN;
GPIO_Init(OLED_CS_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = OLED_SCK_PIN;
GPIO_Init(OLED_SCK_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = OLED_SDIN_PIN;
GPIO_Init(OLED_SDIN_PORT, &GPIO_InitStructure);
}
#else
/* 1.配置GPIO, 设置为FSMC总线。 为了和32位接口兼容,本例子也配置为32位总线,实际只用了其中8位。 */
{
/* bsp_fm_io 已配置fmc。 此处不必重复配置
bsp_InitExtIO();
*/
}
#endif
}
/*
*********************************************************************************************************
* 函 数 名: OLED_WriteCmd
* 功能说明: 向SSD1306发送一字节命令
* 形 参: 命令字
* 返 回 值: 无
*********************************************************************************************************
*/
static void OLED_WriteCmd(uint8_t _ucCmd)
{
#ifdef OLED_SPI3_EN
uint8_t i;
SSD_CS_0();
SSD_SCK_0();
SSD_SDIN_0(); /* 0 表示后面传送的是命令 1表示后面传送的数据 */
SSD_SCK_1();
for (i = 0; i < 8; i++)
{
if (_ucCmd & 0x80)
{
SSD_SDIN_1();
}
else
{
SSD_SDIN_0();
}
SSD_SCK_0();
_ucCmd <<= 1;
SSD_SCK_1();
}
SSD_CS_1();
#else
OLED_CMD = _ucCmd;
#endif
}
/*
*********************************************************************************************************
* 函 数 名: OLED_WriteData
* 功能说明: 向SSD1306发送一字节数据
* 形 参: 命令字
* 返 回 值: 无
*********************************************************************************************************
*/
static void OLED_WriteData(uint8_t _ucData)
{
#ifdef OLED_SPI3_EN
uint8_t i;
SSD_CS_0();
SSD_SCK_0();
SSD_SDIN_1(); /* 0 表示后面传送的是命令 1表示后面传送的数据 */
SSD_SCK_1();
for (i = 0; i < 8; i++)
{
if (_ucData & 0x80)
{
SSD_SDIN_1();
}
else
{
SSD_SDIN_0();
}
SSD_SCK_0();
_ucData <<= 1;
SSD_SCK_1();
}
SSD_CS_1();
#else
OLED_DATA = _ucData;
#endif
}
/***************************** 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url] (END OF FILE) *********************************/