硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2446|回复: 1
收起左侧

[有问必答] 请问12864屏幕串行模式下怎么画点、画线?

[复制链接]

32

主题

103

回帖

199

积分

高级会员

积分
199
发表于 2018-7-10 12:07:10 | 显示全部楼层 |阅读模式
驱动是ST7920,目前可以显示字符、汉字、图片,但是因为是串行,所以不能读取,所以没法画点、画线。手里的程序有画点、画线的,建立一个缓冲区,但是我运行了一下发现不好使,我也没看懂。求一个串行模式下,画点、画线的程序,谢谢各位。
  1. //水平0-7 上半屏 水平8-15 下半屏
  2. //缓存仍以64*8存储,方便ucgui
  3. u16 Lcd_Data_Cache[64][8]={
  4.         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
  5.   {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
  6. };
复制代码

  1. /*************更新一个点的缓存****************/
  2. u16 Refresh_Cache_Point(u8 x,u8 y,u8 bit)
  3. {
  4.         u16 word;
  5.         u8 tmp;
  6.         word=Lcd_Data_Cache[y][x/16];//
  7.         tmp=15-(x%16);
  8.         if(bit) word|=(1<<tmp);
  9.         else    word&=~(1<<tmp);
  10.         Lcd_Data_Cache[y][x/16]=word;
  11.         return word;
  12. }
  13. /**************更新一个字节的缓存*************************/
  14. //xsize 字节中有效的位数 diff:
  15. void Refresh_Cache_Byte(u8 x,u8 y,u8 xsize,u8 diff,u8 data)
  16. {
  17.         u16 word;
  18.         u8 i,bit;
  19.         bit=(x%16);
  20.         word=Lcd_Data_Cache[y][x/16];
  21.         for(i=0;i<xsize;i++)
  22.         {
  23.                 if(data&(0x80>>i))
  24.                 {
  25.                         word|=(0x0001<<(bit+i));
  26.                 }
  27.                 else word&=(~(0x0001<<(bit+i)));
  28.         }
  29.         Lcd_Data_Cache[y][x/16]=word;
  30. }
  31. /***********************画一个字节的数据*******************/
  32. //测试用
  33. void Qc12864_Draw_Byte(u8 x,u8 y,u8 byte)
  34. {
  35.         u16 word;
  36.         word=Lcd_Data_Cache[y][x/16];
  37.         if((x%16)<8)
  38.         {
  39.                 word=(word&0x00ff)+((u16)byte<<8);
  40.           Lcd_Data_Cache[y][x/16]=word;
  41.         }
  42.         else
  43.         {
  44.                 word=(word&0xff00)+((u16)byte);
  45.           Lcd_Data_Cache[y][x/16]=word;
  46.         }
  47.   x=x/16;     //找到像素点所在字的水平位置
  48.         if(y>31)  //是否下半屏
  49.         {
  50.                 y-=32;
  51.                 x+=8;
  52.         }
  53.   Qc12864_WriteCmd(0x80+y);    //设定垂直地址
  54.   Qc12864_WriteCmd(0x80+x);

  55.   Qc12864_WriteData((word>>8)&0xff);        
  56.   Qc12864_WriteData(word&0xff);
  57.                
  58. }
  59. /**********************画几个字的数据*******************/
  60. //注意,len是字长度
  61. void Qc12864_Draw_nWord(u8 x,u8 y,u16* str,u8 len)
  62. {
  63.         u8 i;
  64.         x=x/16;     //找到像素点所在字的水平位置
  65.         if(y>31)  //是否下半屏
  66.         {
  67.                 y-=32;
  68.                 x+=8;
  69.         }
  70.   Qc12864_WriteCmd(0x80+y);    //设定垂直地址
  71.   Qc12864_WriteCmd(0x80+x);
  72.        
  73.         for(i=0;i<len;i++)
  74.         {
  75.                 Qc12864_WriteData((*str>>8)&0xff);
  76.                 Qc12864_WriteData(*str&0xff);
  77.                 str++;
  78.         }
  79. }
  80. /*********************画点函数***************************/
  81. //x:水平坐标 0-127   y:垂直坐标 0-64
  82. //画图时为先水平后垂直扫描方式,故实际为16*64
  83. //串行方式读不出数据,建显存
  84. void Qc12864_Draw_Point(u8 x,u8 y,u8 bit)
  85. {
  86.         u16 word;       
  87.         word=Refresh_Cache_Point(x,y,bit);
  88.         Qc12864_Draw_nWord(x,y,&word,1);
  89. }
复制代码


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2018-7-10 12:22:21 | 显示全部楼层
跟我们OLED驱动方法差不多,都是建立一个缓冲,楼主参考下:

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : OLED显示器驱动模块
  5. *        文件名称 : bsp_oled.c
  6. *        版    本 : V1.0
  7. *        说    明 : OLED 屏(128x64)底层驱动程序,驱动芯片型号为 SSD1306.  本驱动程序适合于STM32-V5开发板.
  8. *                                OLED模块挂在FSMC总线上。
  9. *        修改记录 :
  10. *                版本号  日期        作者    说明
  11. *                V1.0    2013-02-01 armfly  正式发布
  12. *
  13. *        Copyright (C), 2010-2012, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */

  17. #include "bsp.h"
  18. #include "fonts.h"

  19. /*
  20.         安富莱STM32-V4开发板的OLED显示接口为FSMC总线模式。
  21. */

  22. /* 下面2个宏任选 1个; 表示显示方向 */
  23. #define DIR_NORMAL                        /* 此行表示正常显示方向 */
  24. //#define DIR_180                                /* 此行表示翻转180度 */

  25. #ifdef OLED_SPI3_EN
  26.         /*
  27.                 SPI 模式接线定义 (只需要6根杜邦线连接)  本例子采用软件模拟SPI时序

  28.            【OLED模块排针】 【开发板TFT接口(STM32口线)】
  29.                 VCC ----------- 3.3V
  30.                 GND ----------- GND
  31.                  CS ----------- TP_NCS   (PI10)
  32.                 RST ----------- NRESET (也可以不连接)
  33.              D0/SCK ----------- TP_SCK   (PB3)
  34.             D1/SDIN ----------- TP_MOSI  (PB5)
  35.         */
  36.         #define RCC_OLED_PORT (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI)                /* GPIO端口时钟 */

  37.         #define OLED_CS_PORT        GPIOI
  38.         #define OLED_CS_PIN                GPIO_Pin_10

  39.         #define OLED_SCK_PORT        GPIOB
  40.         #define OLED_SCK_PIN        GPIO_Pin_3

  41.         #define OLED_SDIN_PORT        GPIOB
  42.         #define OLED_SDIN_PIN        GPIO_Pin_5


  43.         /* 定义IO = 1和 0的代码 (不用更改) */
  44.         #define SSD_CS_1()                OLED_CS_PORT->BSRRL = OLED_CS_PIN
  45.         #define SSD_CS_0()                OLED_CS_PORT->BSRRH = OLED_CS_PIN

  46.         #define SSD_SCK_1()                OLED_SCK_PORT->BSRRL = OLED_SCK_PIN
  47.         #define SSD_SCK_0()                OLED_SCK_PORT->BSRRH = OLED_SCK_PIN

  48.         #define SSD_SDIN_1()        OLED_SDIN_PORT->BSRRL = OLED_SDIN_PIN
  49.         #define SSD_SDIN_0()        OLED_SDIN_PORT->BSRRH = OLED_SDIN_PIN

  50. #else

  51.         /* 定义LCD驱动器的访问地址
  52.                 TFT接口中的RS引脚连接FSMC_A0引脚,由于是16bit模式,RS对应A1地址线,因此
  53.                 OLED_RAM的地址是+2
  54.         */
  55.         #define OLED_BASE       ((uint32_t)(0x6C200000))
  56.         #define OLED_CMD                *(__IO uint16_t *)(OLED_BASE)
  57.         #define OLED_DATA                *(__IO uint16_t *)(OLED_BASE + (1 << 1))                /* FSMC_A0接D/C */

  58.         /*
  59.         1.安富莱OLED模块 80XX 模式接线定义 (需要15根杜邦线连接)
  60.            【OLED模块排针】 【开发板TFT接口(STM32口线)】
  61.                     VCC ----------- 3.3V
  62.                     GND ----------- GND
  63.                      CS ----------- NCS
  64.                 RST ----------- NRESET (也可以不连接)
  65.                     D/C ----------- RS   (FSMC_A18)
  66.                      WE ----------- NWE  (FSMC_NWE)
  67.                      OE ----------- NOE  (FSMC_NOE)
  68.              D0/SCK ----------- DB0  (FSMC_D0)
  69.                 D1/SDIN ----------- DB1  (FSMC_D1)
  70.                      D2 ----------- DB2  (FSMC_D2)
  71.                      D3 ----------- DB3  (FSMC_D3)
  72.                      D4 ----------- DB4  (FSMC_D4)
  73.                      D5 ----------- DB5  (FSMC_D5)
  74.                      D6 ----------- DB6  (FSMC_D6)
  75.                      D7 ----------- DB7  (FSMC_D7)
  76.         */


  77. #endif

  78. /* 12864 OLED的显存镜像,占用1K字节. 共8行,每行128像素 */
  79. static uint8_t s_ucGRAM[8][128];

  80. /* 为了避免刷屏拉幕感太强,引入刷屏标志。
  81. 0 表示显示函数只改写缓冲区,不写屏。1 表示直接写屏(同时写缓冲区) */
  82. static uint8_t s_ucUpdateEn = 1;

  83. static void OLED_ConfigGPIO(void);
  84. static void OLED_WriteCmd(uint8_t _ucCmd);
  85. static void OLED_WriteData(uint8_t _ucData);
  86. static void OLED_BufToPanel(void);

  87. /*
  88. *********************************************************************************************************
  89. *        函 数 名: OLED_InitHard
  90. *        功能说明: 初始化OLED屏
  91. *        形    参:  无
  92. *        返 回 值: 无
  93. *********************************************************************************************************
  94. */
  95. void OLED_InitHard(void)
  96. {
  97.         OLED_ConfigGPIO();

  98.         /* 上电延迟 */
  99.         bsp_DelayMS(50);

  100.          /* 模块厂家提供初始化代码 */
  101.         OLED_WriteCmd(0xAE);        /* 关闭OLED面板显示(休眠) */
  102.         OLED_WriteCmd(0x00);        /* 设置列地址低4bit */
  103.         OLED_WriteCmd(0x10);        /* 设置列地址高4bit */
  104.         OLED_WriteCmd(0x40);        /* 设置起始行地址(低5bit 0-63), 硬件相关*/

  105.         OLED_WriteCmd(0x81);        /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
  106.         OLED_WriteCmd(0xCF);        /* 设置对比度参数,缺省CF */

  107. #ifdef DIR_NORMAL
  108.         OLED_WriteCmd(0xA0);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
  109.         OLED_WriteCmd(0xC0);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
  110. #endif

  111. #ifdef DIR_180
  112.         OLED_WriteCmd(0xA1);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
  113.         OLED_WriteCmd(0xC8);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
  114. #endif

  115.         OLED_WriteCmd(0xA6);        /* A6 : 设置正常显示模式; A7 : 设置为反显模式 */

  116.         OLED_WriteCmd(0xA8);        /* 设置COM路数 */
  117.         OLED_WriteCmd(0x3F);        /* 1 ->(63+1)路 */

  118.         OLED_WriteCmd(0xD3);        /* 设置显示偏移(双字节命令)*/
  119.         OLED_WriteCmd(0x00);        /* 无偏移 */

  120.         OLED_WriteCmd(0xD5);        /* 设置显示时钟分频系数/振荡频率 */
  121.         OLED_WriteCmd(0x80);        /* 设置分频系数,高4bit是分频系数,低4bit是振荡频率 */

  122.         OLED_WriteCmd(0xD9);        /* 设置预充电周期 */
  123.         OLED_WriteCmd(0xF1);        /* [3:0],PHASE 1; [7:4],PHASE 2; */

  124.         OLED_WriteCmd(0xDA);        /* 设置COM脚硬件接线方式 */
  125.         OLED_WriteCmd(0x12);

  126.         OLED_WriteCmd(0xDB);        /* 设置 vcomh 电压倍率 */
  127.         OLED_WriteCmd(0x40);        /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC  */

  128.         OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用) */
  129.         OLED_WriteCmd(0x14);        /* 0x14 使能充电泵, 0x10 是关闭 */
  130.         OLED_WriteCmd(0xAF);        /* 打开OLED面板 */
  131. }

  132. /*
  133. *********************************************************************************************************
  134. *        函 数 名: OLED_DispOn
  135. *        功能说明: 打开显示
  136. *        形    参:  无
  137. *        返 回 值: 无
  138. *********************************************************************************************************
  139. */
  140. void OLED_DispOn(void)
  141. {
  142.         OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用) */
  143.         OLED_WriteCmd(0x14);        /* 0x14 使能充电泵, 0x10 是关闭 */
  144.         OLED_WriteCmd(0xAF);        /* 打开OLED面板 */
  145. }

  146. /*
  147. *********************************************************************************************************
  148. *        函 数 名: OLED_DispOff
  149. *        功能说明: 关闭显示
  150. *        形    参:  无
  151. *        返 回 值: 无
  152. *********************************************************************************************************
  153. */
  154. void OLED_DispOff(void)
  155. {
  156.         OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用)*/
  157.         OLED_WriteCmd(0x10);        /* 0x14 使能充电泵,0x10 是关闭 */
  158.         OLED_WriteCmd(0xAE);        /* 打开OLED面板 */
  159. }

  160. /*
  161. *********************************************************************************************************
  162. *        函 数 名: OLED_SetDir
  163. *        功能说明: 设置显示方向
  164. *        形    参: _ucDir = 0 表示正常方向,1表示翻转180度
  165. *        返 回 值: 无
  166. *********************************************************************************************************
  167. */
  168. void OLED_SetDir(uint8_t _ucDir)
  169. {
  170.         if (_ucDir == 0)
  171.         {
  172.                OLED_WriteCmd(0xA0);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
  173.                 OLED_WriteCmd(0xC0);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
  174.         }
  175.         else
  176.         {
  177.                 OLED_WriteCmd(0xA1);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
  178.                 OLED_WriteCmd(0xC8);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
  179.         }
  180. }

  181. /*
  182. *********************************************************************************************************
  183. *        函 数 名: OLED_SetContrast
  184. *        功能说明: 设置对比度
  185. *        形    参:  无
  186. *        返 回 值: 无
  187. *********************************************************************************************************
  188. */
  189. void OLED_SetContrast(uint8_t ucValue)
  190. {
  191.         OLED_WriteCmd(0x81);        /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
  192.         OLED_WriteCmd(ucValue);        /* 设置对比度参数,缺省CF */
  193. }

  194. /*
  195. *********************************************************************************************************
  196. *        函 数 名: OLED_StartDraw
  197. *        功能说明: 开始绘图。以后绘图函数只改写缓冲区,不改写面板显存
  198. *        形    参:  无
  199. *        返 回 值: 无
  200. *********************************************************************************************************
  201. */
  202. void OLED_StartDraw(void)
  203. {
  204.         s_ucUpdateEn = 0;
  205. }

  206. /*
  207. *********************************************************************************************************
  208. *        函 数 名: OLED_EndDraw
  209. *        功能说明: 结束绘图。缓冲区的数据刷新到面板显存。 OLED_StartDraw() 和 OLED_EndDraw() 必须成对使用
  210. *        形    参:  无
  211. *        返 回 值: 无
  212. *********************************************************************************************************
  213. */
  214. void OLED_EndDraw(void)
  215. {
  216.         s_ucUpdateEn = 1;
  217.         OLED_BufToPanel();
  218. }

  219. /*
  220. *********************************************************************************************************
  221. *        函 数 名: OLED_ClrScr
  222. *        功能说明: 清屏
  223. *        形    参:  _ucMode : 0 表示全黑; 0xFF表示全亮
  224. *        返 回 值: 无
  225. *********************************************************************************************************
  226. */
  227. void OLED_ClrScr(uint8_t _ucMode)
  228. {
  229.         uint8_t i,j;

  230.         for (i = 0 ; i < 8; i++)
  231.         {
  232.                 for (j = 0 ; j < 128; j++)
  233.                 {
  234.                         s_ucGRAM[i][j] = _ucMode;
  235.                 }
  236.         }

  237.         if (s_ucUpdateEn == 1)
  238.         {
  239.                 OLED_BufToPanel();
  240.         }
  241. }

  242. /*
  243. *********************************************************************************************************
  244. *        函 数 名: OLED_BufToPanel
  245. *        功能说明: 将缓冲区中的点阵数据写入面板
  246. *        形    参:  无
  247. *        返 回 值: 无
  248. *********************************************************************************************************
  249. */
  250. static void OLED_BufToPanel(void)
  251. {
  252.         uint8_t i,j;

  253.         for (i = 0 ; i< 8; i++)
  254.         {
  255.                 OLED_WriteCmd (0xB0 + i);        /* 设置页地址(0~7) */
  256.                 OLED_WriteCmd (0x00);                /* 设置列地址的低地址 */
  257.                 OLED_WriteCmd (0x10);                /* 设置列地址的高地址 */

  258.                 for (j = 0 ; j < 128; j++)
  259.                 {
  260.                         OLED_WriteData(s_ucGRAM[i][j]);
  261.                 }
  262.         }
  263. }

  264. /*
  265. *********************************************************************************************************
  266. *        函 数 名: OLED_DispStr
  267. *        功能说明: 在屏幕指定坐标(左上角为0,0)显示一个字符串
  268. *        形    参:
  269. *                _usX : X坐标,对于12864屏,范围为【0 - 127】
  270. *                _usY : Y坐标,对于12864屏,范围为【0 - 63】
  271. *                _ptr  : 字符串指针
  272. *                _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数
  273. *        返 回 值: 无
  274. *********************************************************************************************************
  275. */
  276. void OLED_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont)
  277. {
  278.         uint32_t i;
  279.         uint8_t code1;
  280.         uint8_t code2;
  281.         uint32_t address = 0;
  282.         uint8_t buf[32 * 32 / 8];        /* 最大支持32点阵汉字 */
  283.         uint8_t m, width;
  284.         uint8_t font_width,font_height, font_bytes;
  285.         uint16_t x, y;
  286.         const uint8_t *pAscDot;       

  287. #ifdef USE_SMALL_FONT               
  288.         const uint8_t *pHzDot;
  289. #else       
  290.         uint32_t AddrHZK;
  291. #endif       

  292.         /* 如果字体结构为空指针,则缺省按16点阵 */
  293.         if (_tFont->FontCode == FC_ST_12)
  294.         {
  295.                 font_height = 12;
  296.                 font_width = 12;
  297.                 font_bytes = 24;
  298.                 pAscDot = g_Ascii12;
  299.         #ifdef USE_SMALL_FONT               
  300.                 pHzDot = g_Hz12;
  301.         #else               
  302.                 AddrHZK = HZK12_ADDR;
  303.         #endif               
  304.         }
  305.         else
  306.         {
  307.                 /* 缺省是16点阵 */
  308.                 font_height = 16;
  309.                 font_width = 16;
  310.                 font_bytes = 32;
  311.                 pAscDot = g_Ascii16;
  312.         #ifdef USE_SMALL_FONT               
  313.                 pHzDot = g_Hz16;
  314.         #else
  315.                 AddrHZK = HZK16_ADDR;
  316.         #endif
  317.         }

  318.         /* 开始循环处理字符 */
  319.         while (*_ptr != 0)
  320.         {
  321.                 code1 = *_ptr;        /* 读取字符串数据, 该数据可能是ascii代码,也可能汉字代码的高字节 */
  322.                 if (code1 < 0x80)
  323.                 {
  324.                         /* 将ascii字符点阵复制到buf */
  325.                         memcpy(buf, &pAscDot[code1 * (font_bytes / 2)], (font_bytes / 2));
  326.                         width = font_width / 2;
  327.                 }
  328.                 else
  329.                 {
  330.                         code2 = *++_ptr;
  331.                         if (code2 == 0)
  332.                         {
  333.                                 break;
  334.                         }

  335.                         /* 计算16点阵汉字点阵地址
  336.                                 ADDRESS = [(code1-0xa1) * 94 + (code2-0xa1)] * 32
  337.                                 ;
  338.                         */
  339.                         #ifdef USE_SMALL_FONT
  340.                                 m = 0;
  341.                                 while(1)
  342.                                 {
  343.                                         address = m * (font_bytes + 2);
  344.                                         m++;
  345.                                         if ((code1 == pHzDot[address + 0]) && (code2 == pHzDot[address + 1]))
  346.                                         {
  347.                                                 address += 2;
  348.                                                 memcpy(buf, &pHzDot[address], font_bytes);
  349.                                                 break;
  350.                                         }
  351.                                         else if ((pHzDot[address + 0] == 0xFF) && (pHzDot[address + 1] == 0xFF))
  352.                                         {
  353.                                                 /* 字库搜索完毕,未找到,则填充全FF */
  354.                                                 memset(buf, 0xFF, font_bytes);
  355.                                                 break;
  356.                                         }
  357.                                 }
  358.                         #else        /* 用全字库 */
  359.                                 /* 此处需要根据字库文件存放位置进行修改 */
  360.                                 if (code1 >=0xA1 && code1 <= 0xA9 && code2 >=0xA1)
  361.                                 {
  362.                                         address = ((code1 - 0xA1) * 94 + (code2 - 0xA1)) * font_bytes + AddrHZK;
  363.                                 }
  364.                                 else if (code1 >=0xB0 && code1 <= 0xF7 && code2 >=0xA1)
  365.                                 {
  366.                                         address = ((code1 - 0xB0) * 94 + (code2 - 0xA1) + 846) * font_bytes + AddrHZK;
  367.                                 }
  368.                                 memcpy(buf, (const uint8_t *)address, font_bytes);
  369.                         #endif

  370.                                 width = font_width;
  371.                 }

  372.                 y = _usY;
  373.                 /* 开始刷LCD */
  374.                 for (m = 0; m < font_height; m++)        /* 字符高度 */
  375.                 {
  376.                         x = _usX;
  377.                         for (i = 0; i < width; i++)        /* 字符宽度 */
  378.                         {
  379.                                 if ((buf[m * ((2 * width) / font_width) + i / 8] & (0x80 >> (i % 8 ))) != 0x00)
  380.                                 {
  381.                                         OLED_PutPixel(x, y, _tFont->FrontColor);        /* 设置像素颜色为文字色 */
  382.                                 }
  383.                                 else
  384.                                 {
  385.                                         OLED_PutPixel(x, y, _tFont->BackColor);        /* 设置像素颜色为文字背景色 */
  386.                                 }

  387.                                 x++;
  388.                         }
  389.                         y++;
  390.                 }

  391.                 if (_tFont->Space > 0)
  392.                 {
  393.                         /* 如果文字底色按_tFont->usBackColor,并且字间距大于点阵的宽度,那么需要在文字之间填充(暂时未实现) */
  394.                 }
  395.                 _usX += width + _tFont->Space;        /* 列地址递增 */
  396.                 _ptr++;                        /* 指向下一个字符 */
  397.         }
  398. }

  399. /*
  400. *********************************************************************************************************
  401. *        函 数 名: OLED_PutPixel
  402. *        功能说明: 画1个像素
  403. *        形    参:
  404. *                        _usX,_usY : 像素坐标
  405. *                        _ucColor  :像素颜色
  406. *        返 回 值: 无
  407. *********************************************************************************************************
  408. */
  409. void OLED_PutPixel(uint16_t _usX, uint16_t _usY, uint8_t _ucColor)
  410. {
  411.         uint8_t ucValue;
  412.         uint8_t ucPageAddr;
  413.         uint8_t ucColAddr;

  414.         const uint8_t aOrTab[8]  = {0x01, 0x02, 0x04, 0x08,0x10,0x20,0x40,0x80};
  415.         const uint8_t aAndTab[8] = {0xFE, 0xFD, 0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F};

  416.         ucPageAddr = _usY / 8;
  417.         ucColAddr = _usX;

  418.         ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
  419.         if (_ucColor == 0)
  420.         {
  421.                 ucValue &= aAndTab[_usY % 8];
  422.         }
  423.         else
  424.         {
  425.                 ucValue |= aOrTab[_usY % 8];
  426.         }
  427.         s_ucGRAM[ucPageAddr][ucColAddr] = ucValue;

  428.         if (s_ucUpdateEn == 1)
  429.         {
  430.                 OLED_WriteCmd (0xB0 + ucPageAddr);                                        /* 设置页地址(0~7) */
  431.                 OLED_WriteCmd (0x00 + (ucColAddr & 0x0F));                        /* 设置列地址的低地址 */
  432.                 OLED_WriteCmd (0x10 + ((ucColAddr >> 4) & 0x0F));        /* 设置列地址的高地址 */
  433.                 OLED_WriteData(ucValue);
  434.         }
  435. }

  436. /*
  437. *********************************************************************************************************
  438. *        函 数 名: OLED_GetPixel
  439. *        功能说明: 读取1个像素
  440. *        形    参:
  441. *                        _usX,_usY : 像素坐标
  442. *        返 回 值: 颜色值 (0, 1)
  443. *********************************************************************************************************
  444. */
  445. uint8_t OLED_GetPixel(uint16_t _usX, uint16_t _usY)
  446. {
  447.         uint8_t ucValue;
  448.         uint8_t ucPageAddr;
  449.         uint8_t ucColAddr;

  450.         ucPageAddr = _usY / 8;
  451.         ucColAddr = _usX;

  452.         ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
  453.         if (ucValue & (_usY % 8))
  454.         {
  455.                 return 1;
  456.         }
  457.         else
  458.         {
  459.                 return 0;
  460.         }
  461. }

  462. /*
  463. *********************************************************************************************************
  464. *        函 数 名: OLED_DrawLine
  465. *        功能说明: 采用 Bresenham 算法,在2点间画一条直线。
  466. *        形    参:
  467. *                        _usX1, _usY1 :起始点坐标
  468. *                        _usX2, _usY2 :终止点Y坐标
  469. *                        _ucColor     :颜色
  470. *        返 回 值: 无
  471. *********************************************************************************************************
  472. */
  473. void OLED_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint8_t _ucColor)
  474. {
  475.         int32_t dx , dy ;
  476.         int32_t tx , ty ;
  477.         int32_t inc1 , inc2 ;
  478.         int32_t d , iTag ;
  479.         int32_t x , y ;

  480.         /* 采用 Bresenham 算法,在2点间画一条直线 */

  481.         OLED_PutPixel(_usX1 , _usY1 , _ucColor);

  482.         /* 如果两点重合,结束后面的动作。*/
  483.         if ( _usX1 == _usX2 && _usY1 == _usY2 )
  484.         {
  485.                 return;
  486.         }

  487.         iTag = 0 ;
  488.         /* dx = abs ( _usX2 - _usX1 ); */
  489.         if (_usX2 >= _usX1)
  490.         {
  491.                 dx = _usX2 - _usX1;
  492.         }
  493.         else
  494.         {
  495.                 dx = _usX1 - _usX2;
  496.         }

  497.         /* dy = abs ( _usY2 - _usY1 ); */
  498.         if (_usY2 >= _usY1)
  499.         {
  500.                 dy = _usY2 - _usY1;
  501.         }
  502.         else
  503.         {
  504.                 dy = _usY1 - _usY2;
  505.         }

  506.         if ( dx < dy )   /*如果dy为计长方向,则交换纵横坐标。*/
  507.         {
  508.                 uint16_t temp;

  509.                 iTag = 1 ;
  510.                 temp = _usX1; _usX1 = _usY1; _usY1 = temp;
  511.                 temp = _usX2; _usX2 = _usY2; _usY2 = temp;
  512.                 temp = dx; dx = dy; dy = temp;
  513.         }
  514.         tx = _usX2 > _usX1 ? 1 : -1 ;    /* 确定是增1还是减1 */
  515.         ty = _usY2 > _usY1 ? 1 : -1 ;
  516.         x = _usX1 ;
  517.         y = _usY1 ;
  518.         inc1 = 2 * dy ;
  519.         inc2 = 2 * ( dy - dx );
  520.         d = inc1 - dx ;
  521.         while ( x != _usX2 )     /* 循环画点 */
  522.         {
  523.                 if ( d < 0 )
  524.                 {
  525.                         d += inc1 ;
  526.                 }
  527.                 else
  528.                 {
  529.                         y += ty ;
  530.                         d += inc2 ;
  531.                 }
  532.                 if ( iTag )
  533.                 {
  534.                         OLED_PutPixel ( y , x , _ucColor) ;
  535.                 }
  536.                 else
  537.                 {
  538.                         OLED_PutPixel ( x , y , _ucColor) ;
  539.                 }
  540.                 x += tx ;
  541.         }
  542. }

  543. /*
  544. *********************************************************************************************************
  545. *        函 数 名: OLED_DrawPoints
  546. *        功能说明: 采用 Bresenham 算法,绘制一组点,并将这些点连接起来。可用于波形显示。
  547. *        形    参:
  548. *                        x, y     :坐标数组
  549. *                        _ucColor :颜色
  550. *        返 回 值: 无
  551. *********************************************************************************************************
  552. */
  553. void OLED_DrawPoints(uint16_t *x, uint16_t *y, uint16_t _usSize, uint8_t _ucColor)
  554. {
  555.         uint16_t i;

  556.         for (i = 0 ; i < _usSize - 1; i++)
  557.         {
  558.                 OLED_DrawLine(x[i], y[i], x[i + 1], y[i + 1], _ucColor);
  559.         }
  560. }

  561. /*
  562. *********************************************************************************************************
  563. *        函 数 名: OLED_DrawRect
  564. *        功能说明: 绘制矩形。
  565. *        形    参:
  566. *                        _usX,_usY:矩形左上角的坐标
  567. *                        _usHeight :矩形的高度
  568. *                        _usWidth  :矩形的宽度
  569. *        返 回 值: 无
  570. *********************************************************************************************************
  571. */
  572. void OLED_DrawRect(uint16_t _usX, uint16_t _usY, uint8_t _usHeight, uint16_t _usWidth, uint8_t _ucColor)
  573. {
  574.         /*
  575.          ---------------->---
  576.         |(_usX,_usY)        |
  577.         V                    V  _usHeight
  578.         |                    |
  579.          ---------------->---
  580.                   _usWidth
  581.         */

  582.         OLED_DrawLine(_usX, _usY, _usX + _usWidth - 1, _usY, _ucColor);        /* 顶 */
  583.         OLED_DrawLine(_usX, _usY + _usHeight - 1, _usX + _usWidth - 1, _usY + _usHeight - 1, _ucColor);        /* 底 */

  584.         OLED_DrawLine(_usX, _usY, _usX, _usY + _usHeight - 1, _ucColor);        /* 左 */
  585.         OLED_DrawLine(_usX + _usWidth - 1, _usY, _usX + _usWidth - 1, _usY + _usHeight, _ucColor);        /* 右 */
  586. }

  587. /*
  588. *********************************************************************************************************
  589. *        函 数 名: OLED_DrawCircle
  590. *        功能说明: 绘制一个圆,笔宽为1个像素
  591. *        形    参:
  592. *                        _usX,_usY  :圆心的坐标
  593. *                        _usRadius  :圆的半径
  594. *        返 回 值: 无
  595. *********************************************************************************************************
  596. */
  597. void OLED_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint8_t _ucColor)
  598. {
  599.         int32_t  D;                        /* Decision Variable */
  600.         uint32_t  CurX;                /* 当前 X 值 */
  601.         uint32_t  CurY;                /* 当前 Y 值 */

  602.         D = 3 - (_usRadius << 1);
  603.         CurX = 0;
  604.         CurY = _usRadius;

  605.         while (CurX <= CurY)
  606.         {
  607.                 OLED_PutPixel(_usX + CurX, _usY + CurY, _ucColor);
  608.                 OLED_PutPixel(_usX + CurX, _usY - CurY, _ucColor);
  609.                 OLED_PutPixel(_usX - CurX, _usY + CurY, _ucColor);
  610.                 OLED_PutPixel(_usX - CurX, _usY - CurY, _ucColor);
  611.                 OLED_PutPixel(_usX + CurY, _usY + CurX, _ucColor);
  612.                 OLED_PutPixel(_usX + CurY, _usY - CurX, _ucColor);
  613.                 OLED_PutPixel(_usX - CurY, _usY + CurX, _ucColor);
  614.                 OLED_PutPixel(_usX - CurY, _usY - CurX, _ucColor);

  615.                 if (D < 0)
  616.                 {
  617.                         D += (CurX << 2) + 6;
  618.                 }
  619.                 else
  620.                 {
  621.                         D += ((CurX - CurY) << 2) + 10;
  622.                         CurY--;
  623.                 }
  624.                 CurX++;
  625.         }
  626. }

  627. /*
  628. *********************************************************************************************************
  629. *        函 数 名: OLED_DrawBMP
  630. *        功能说明: 在LCD上显示一个BMP位图,位图点阵扫描次序:从左到右,从上到下
  631. *        形    参:
  632. *                        _usX, _usY : 图片的坐标
  633. *                        _usHeight  :图片高度
  634. *                        _usWidth   :图片宽度
  635. *                        _ptr       :单色图片点阵指针,每个像素占用1个字节
  636. *        返 回 值: 无
  637. *********************************************************************************************************
  638. */
  639. void OLED_DrawBMP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint8_t *_ptr)
  640. {
  641.         uint16_t x, y;

  642.         for (x = 0; x < _usWidth; x++)
  643.         {
  644.                 for (y = 0; y < _usHeight; y++)
  645.                 {
  646.                         OLED_PutPixel(_usX + x, _usY + y, *_ptr);
  647.                 }
  648.         }
  649. }

  650. /*
  651. *********************************************************************************************************
  652. *        函 数 名: OLED_ConfigGPIO
  653. *        功能说明: 配置OLED控制口线,设置为8位80XX总线控制模式或SPI模式
  654. *        形    参:  无
  655. *        返 回 值: 无
  656. *********************************************************************************************************
  657. */
  658. static void OLED_ConfigGPIO(void)
  659. {
  660.         /* 12.配置GPIO */
  661.         {
  662.                 GPIO_InitTypeDef GPIO_InitStructure;

  663.                 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

  664.                 /* 使能 FSMC, GPIOD, GPIOE, GPIOF, GPIOG 和 AFIO 时钟 */
  665.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
  666.                                                          RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
  667.                                                          RCC_APB2Periph_AFIO, ENABLE);

  668.                 /* 设置 PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
  669.                  PD.10(D15), PD.14(D0), PD.15(D1) 为复用推挽输出 */
  670.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
  671.                                                                         GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
  672.                                                                         GPIO_Pin_15;
  673.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  674.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  675.                 GPIO_Init(GPIOD, &GPIO_InitStructure);

  676.                 /* 设置 PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
  677.                  PE.14(D11), PE.15(D12) 为复用推挽输出 */
  678.                 /* PE3,PE4 用于A19, A20, STM32F103ZE-EK(REV 1.0)必须使能 */
  679.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
  680.                                                                         GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
  681.                                                                         GPIO_Pin_15 | GPIO_Pin_3 | GPIO_Pin_4;
  682.                 GPIO_Init(GPIOE, &GPIO_InitStructure);

  683.                 /* 设置 PF.00(A0 (RS))  为复用推挽输出 */
  684.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  685.                 GPIO_Init(GPIOF, &GPIO_InitStructure);

  686.                 /* 设置 PG.12(NE4 (LCD/CS)) 为复用推挽输出 */
  687.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  688.                 GPIO_Init(GPIOG, &GPIO_InitStructure);
  689.         }

  690.         /* 2.配置FSMC总线参数 */
  691.         {
  692.                 FSMC_NORSRAMInitTypeDef  init;
  693.                 FSMC_NORSRAMTimingInitTypeDef  timing;

  694.                 /*-- FSMC Configuration ------------------------------------------------------*/
  695.                 /*----------------------- SRAM Bank 4 ----------------------------------------*/
  696.                 /* FSMC_Bank1_NORSRAM4 configuration */
  697.                 timing.FSMC_AddressSetupTime = 1;
  698.                 timing.FSMC_AddressHoldTime = 0;
  699.                 timing.FSMC_DataSetupTime = 2;
  700.                 timing.FSMC_BusTurnAroundDuration = 0;
  701.                 timing.FSMC_CLKDivision = 0;
  702.                 timing.FSMC_DataLatency = 0;
  703.                 timing.FSMC_AccessMode = FSMC_AccessMode_A;

  704.                 /*
  705.                  LCD configured as follow:
  706.                         - Data/Address MUX = Disable
  707.                         - Memory Type = SRAM
  708.                         - Data Width = 16bit
  709.                         - Write Operation = Enable
  710.                         - Extended Mode = Enable
  711.                         - Asynchronous Wait = Disable
  712.                 */
  713.                 init.FSMC_Bank = FSMC_Bank1_NORSRAM4;
  714.                 init.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  715.                 init.FSMC_MemoryType = FSMC_MemoryType_SRAM;
  716.                 init.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  717.                 init.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  718.                 init.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;        /* 注意旧库无这个成员 */
  719.                 init.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  720.                 init.FSMC_WrapMode = FSMC_WrapMode_Disable;
  721.                 init.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  722.                 init.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  723.                 init.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  724.                 init.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  725.                 init.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

  726.                 init.FSMC_ReadWriteTimingStruct = &timing;
  727.                 init.FSMC_WriteTimingStruct = &timing;

  728.                 FSMC_NORSRAMInit(&init);

  729.                 /* - BANK 3 (of NOR/SRAM Bank 1~4) is enabled */
  730.                 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
  731.         }
  732. }

  733. /*
  734. *********************************************************************************************************
  735. *        函 数 名: OLED_WriteCmd
  736. *        功能说明: 向SSD1306发送一字节命令
  737. *        形    参:  命令字
  738. *        返 回 值: 无
  739. *********************************************************************************************************
  740. */
  741. static void OLED_WriteCmd(uint8_t _ucCmd)
  742. {
  743. #ifdef OLED_SPI3_EN
  744.         uint8_t i;

  745.         SSD_CS_0();

  746.         SSD_SCK_0();
  747.         SSD_SDIN_0();        /* 0 表示后面传送的是命令 1表示后面传送的数据 */
  748.         SSD_SCK_1();

  749.         for (i = 0; i < 8; i++)
  750.         {
  751.                 if (_ucCmd & 0x80)
  752.                 {
  753.                         SSD_SDIN_1();
  754.                 }
  755.                 else
  756.                 {
  757.                         SSD_SDIN_0();
  758.                 }
  759.                 SSD_SCK_0();
  760.                 _ucCmd <<= 1;
  761.                 SSD_SCK_1();
  762.         }

  763.         SSD_CS_1();
  764. #else
  765.         OLED_CMD = _ucCmd;
  766. #endif
  767. }

  768. /*
  769. *********************************************************************************************************
  770. *        函 数 名: OLED_WriteData
  771. *        功能说明: 向SSD1306发送一字节数据
  772. *        形    参:  命令字
  773. *        返 回 值: 无
  774. *********************************************************************************************************
  775. */
  776. static void OLED_WriteData(uint8_t _ucData)
  777. {
  778. #ifdef OLED_SPI3_EN
  779.         uint8_t i;

  780.         SSD_CS_0();

  781.         SSD_SCK_0();
  782.         SSD_SDIN_1();        /* 0 表示后面传送的是命令 1表示后面传送的数据 */
  783.         SSD_SCK_1();

  784.         for (i = 0; i < 8; i++)
  785.         {
  786.                 if (_ucData & 0x80)
  787.                 {
  788.                         SSD_SDIN_1();
  789.                 }
  790.                 else
  791.                 {
  792.                         SSD_SDIN_0();
  793.                 }
  794.                 SSD_SCK_0();
  795.                 _ucData <<= 1;
  796.                 SSD_SCK_1();
  797.         }

  798.         SSD_CS_1();
  799. #else
  800.         OLED_DATA = _ucData;
  801. #endif
  802. }

  803. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 01:23 , Processed in 0.153222 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表