【STM32】HAL库 STM32G4适配OLED屏幕_硬件SPI协议

OLED屏幕使用的是7针SPI协议,使用DMA进行传输,同时使用“闪存”。

文件下载连接:STM32 使用硬件SPI驱动0.96寸七针OLED显示器(HAL库)

 * 定义模拟显存
 */
static uint8_t oled_gram[128][8];

一、CUBEMX配置

1.时钟配置

2.SPI配置

SPI Mode选择:Transmit Only Master

Transmit Only Master    仅发送主模式

各个Setting的配置:

3.GPIO配置

GPIO引脚为:

二、代码部分

    OLED.c

#include "oled.h"
#include "oledFont.h"
#include <string.h>

/*********************************************************************
 * ????
 */
#define OLED_CS_H()     HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_SET)
#define OLED_CS_L()     HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_RESET)

#define OLED_DC_H()     HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET)
#define OLED_DC_L()     HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET)

#define OLED_RST_H()    HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET)
#define OLED_RST_L()    HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET)

#define OLED_CMD        0
#define OLED_DATA       1

/*********************************************************************
 * ??????
 */
#define PAGE_SIZE    8
#define WIDTH 	     128
/*********************************************************************
 * ??????
 */
extern SPI_HandleTypeDef hspi1;

/*********************************************************************
 * 定义模拟显存
 */
static uint8_t oled_gram[128][8];
uint32_t FPS;
uint32_t FPS_Count = 0;
/*********************************************************************
 * ???????
 */
static void OLED_WriteByte(uint8_t data, uint8_t cmd);
static void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t mode);
static uint32_t OLED_MyPow(uint8_t m, uint8_t n);
void OLED_WR_Byte(uint8_t dat,uint8_t cmd);
void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode);


/*********************************************************************
 * @fn      OLED_WriteData
 *
 * @brief   ??OLED???h?????
 *
 * @param   data - ?????????/??????
 *          len  - ????????
 *          cmd  - ????/?????? 0,???????;1,???????
 *
 * @return  none
 */
static void OLED_WriteByte(uint8_t data, uint8_t cmd)
{
    if (cmd)
        OLED_DC_H();
    else
        OLED_DC_L();

    //OLED_CS_L();
    HAL_SPI_Transmit(&hspi1, &data, 1, 0x00FF);
    //OLED_CS_H();
    OLED_DC_H();
}

/*********************************************************************
//u8 OLED_GRAM[8][128];			//定义模拟显存
//画点 
//x:0~127
//y:0~63
//t:1(OLED_LED_LIGHTUP) 填充 ; 0(OLED_LED_EXTINGUISH),清空
 */
static void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t mode)
{
    uint8_t pos, bx, temp = 0;

    if (x > 127 || y > 63)  //超出范围了.
        return;

    pos = 7 - y / 8;
    bx = y % 8;
    temp = 1 << (7 - bx);
    if (mode)
        oled_gram[x][pos] |= temp;
    else
        oled_gram[x][pos] &=~temp;
}

/*********************************************************************
 * @fn      OLED_MyPow
 *
 * @brief   m^n
 *
 * @param   m, n
 *
 * @return  result
 */
static uint32_t OLED_MyPow(uint8_t m, uint8_t n)
{
    uint32_t result = 1;
    while (n--)
        result *= m;
    return result;
}

/*********************************************************************
 * ??????
 */
/*********************************************************************
 * @fn      OLED_DisplayOn
 *
 * @brief   ????OLED???
 *
 * @param   none
 *
 * @return  none
 */
void OLED_DisplayOn(void)
{
//    uint8_t data[3];
//    data[0] = 0x8D; // SET DCDC????
//    data[1] = 0x14; // DCDC ON
//    data[2] = 0xAF; // DISPLAY ON
//    OLED_WriteData(data, 3, OLED_CMD);

    OLED_WriteByte(0X8D, OLED_CMD);  //SET DCDC????
    OLED_WriteByte(0X14, OLED_CMD);  //DCDC ON
    OLED_WriteByte(0XAF, OLED_CMD);  //DISPLAY ON
}

/*********************************************************************
 * @fn      OLED_DisplayOn
 *
 * @brief   ???OLED???
 *
 * @param   none
 *
 * @return  none
 */
void OLED_DisplayOff(void)
{
//    uint8_t data[3];
//    data[0] = 0x8D; // SET DCDC????
//    data[1] = 0x10; // DCDC OFF
//    data[2] = 0xAE; // DISPLAY OFF
//    OLED_WriteData(data, 3, OLED_CMD);

    OLED_WriteByte(0X8D, OLED_CMD);  //SET DCDC????
    OLED_WriteByte(0X10, OLED_CMD);  //DCDC OFF
    OLED_WriteByte(0XAE, OLED_CMD);  //DISPLAY OFF
}

/*********************************************************************
 * @fn      OLED_Refresh
 *
 * @brief   ???OLED
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Refresh(void)
{
	++FPS_Count;
    HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)oled_gram, 128 * 8);
}

/*********************************************************************
 * @fn      OLED_Clear
 *
 * @brief   ????
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Clear(void)
{
    uint8_t i, j;
    for (i = 0; i < 128; i++)
        for (j = 0; j < 8; j++)
            oled_gram[i][j] = 0;

    OLED_Refresh();
}

/*********************************************************************
 * @fn      OLED_Fill
 *
 * @brief   ???????K??????
 *
 * @param   x1,y1,x2,y2 - ???????????
 *          mode - 0:???; 1:???
 *
 * @return  none
 */
void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
    uint8_t x, y;
    for (x = x1; x <= x2; x++)
        for (y = y1; y <= y2; y++)
            OLED_DrawPoint(x, y, mode);

    OLED_Refresh();
}

/*********************************************************************
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0(OLED_DISPLAYCHAR_REVERSE)反白显示;1(OLED_DISPLAYCHAR_NORMAL),正常显示  				 
//size:选择字体 8/12/16/24 (列高)
 */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode)
{
    uint8_t temp, t, t1;
    uint8_t y0 = y;
    uint8_t cSize = (size / 8 + ((size % 8) ? 1:0)) * (size / 2);   //得到字体一个字符对应点阵集所占的字节数

    chr = chr - ' ';//得到偏移后的值	
    for(t = 0; t < cSize; t++)
    {
        if (size == 12)
            temp = asc2_1206[chr][t];                //调用1206字体
        else if (size == 16)
            temp = asc2_1608[chr][t];               //调用1608字体
        else if (size == 24)
            temp = asc2_2412[chr][t];               //调用2412字体
        else
            return;                                 //没有的字库

        for(t1 = 0; t1 < 8; t1++)
        {
            if (temp & 0x80)
                OLED_DrawPoint(x , y, mode);
            else
                OLED_DrawPoint(x, y, !mode);
            temp <<= 1;
            y++;
            if ((y - y0) == size)
            {
                y = y0;
                x++;
                break;
            }
        }
    }
}

/*********************************************************************
 * @fn      OLED_ShowNum
 *
 */
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size)
{
    uint8_t t, temp;
    uint8_t enShow = 0;
    for (t = 0; t < len; t++)
    {
        temp = (num / OLED_MyPow(10, len - t - 1)) % 10;
        if(enShow == 0 && t < (len - 1))
        {
            if(temp == 0)
            {
                OLED_ShowChar(x + (size / 2) * t, y ,' ', size, 1);
                continue;
            }
            else
                enShow = 1;

        }
        OLED_ShowChar(x + (size / 2) * t, y, temp + '0', size, 1);
    }
}

//显示字符串
//x,y:起点坐标  
//*p:字符串起始地址
//mode:0(OLED_DISPLAYCHAR_REVERSE)反白显示;1(OLED_DISPLAYCHAR_NORMAL),正常显示  				 
//size:选择字体 12/16/24
void OLED_ShowString(uint8_t x, uint8_t y,uint8_t *pChar, uint8_t size1,uint8_t mode)
{
	while(*pChar!='\0')
   {
        if(((*pChar>=' ')&&(*pChar<='~')))
        {
          if(size1==8)
          {
            if( (x+6)>128 )
              x=0;
              y=y+size1;
          }
          else if( (x+size1/2) > 128) 
          {
              x=0;
              y=y+size1;                  
          }
          OLED_ShowChar(x,y,*pChar,size1,mode);
          if(size1==8)x+=6;
          else x+=size1/2;
          pChar++;
        }
        else
        {
          
          if(size1==8)
          {
            if( (x+6)>128 )
              x=0;
              y=y+size1;
          }
          else if( (x+size1) > 128) 
          {
              x=0;
              y=y+size1;                  
          }
          
            OLED_DisShowCHinese(x,y,pChar,size1,mode);
            if(size1==8)x+=6;
            else x+=size1;
            pChar+=2;         
        }   
   
   }
	 OLED_Refresh();
}

void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{
	OLED_CS_L();
	if(cmd)
	  OLED_DC_H();
	else
	  OLED_DC_L();
 
	HAL_SPI_Transmit(&hspi1,&dat,1,10);
	OLED_DC_H();
	OLED_CS_H();
}

 void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 
 OLED_WriteByte(0xb0+y,OLED_CMD);
 OLED_WriteByte(((x&0xf0)>>4)|0x10,OLED_CMD);
	 OLED_WriteByte((x&0x0f),OLED_CMD); 

} 

//显示汉字
 void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode)
{      			    
  int index=0;
	uint8_t m,temp;
	uint8_t x0=x,y0=y;
	uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1;  //得到字体一个字符对应点阵集所占的字节数
	for(i=0;i<size3;i++)
	{
		if(size1==16)                 
                {
                  for (index=0;index<sizeof(Hzk)/35;index++)
                  {
                    if(Hzk[index].name[0] == pChar[0]&&Hzk[index].name[1] == pChar[1])//对比汉字区码位码
                       temp=Hzk[index].dat[i];                  
                  }
                
                }
//		else if(size1==24)
//				{temp=Hzk2[num][i];}//调用24*24字体
//		else if(size1==32)       
//				{temp=Hzk3[num][i];}//调用32*32字体
//		else if(size1==64)
//				{temp=Hzk4[num][i];}//调用64*64字体
		else return;
		for(m=0;m<8;m++)
		{
			if(temp&0x01)OLED_DrawPoint(x,y,mode);
			else OLED_DrawPoint(x,y,!mode);
			temp>>=1;
			y++;
		}
		x++;
		if((x-x0)==size1)
		{x=x0;y0=y0+8;}
		y=y0;
	}
}

/********************************************************************************
* @函数名:         OLED_DrawBMP
* @函数描述:       在指定位置显示一张图片
* @函数作者:       矛盾聚合体
* @输入参数:
                    参数名    参数类型  参数描述  
                    @x0:     unsignedchar 左上角x坐标,0~127
                    @y0:     unsignedchar 左上角y坐标,0~7
                    @x1:     unsignedchar 右下角x坐标,0~127
                    @y1:     unsignedchar 左下角y坐标,0~7
                    @BMP[]:  unsignedchar 图片数据 
* @返回值:         void
* @其他:           
********************************************************************************/
void OLED_DrawBMP(uint8_t x, uint8_t y, const char* name)
{ 	
    // 查找BMP数据
    const picture* bmp_data = NULL;
    for (int i = 0; i < sizeof(BMP) / sizeof(picture); i++) {
        if (strcmp(BMP[i].name, name) == 0) {
            bmp_data = &BMP[i];
            break;
        }
    }
    
    if (bmp_data == NULL) {
        return;  // 找不到对应的BMP数据
    }

    // 每张图片的宽度和高度
    uint8_t width = 64;
    uint8_t height = 64;

    // 计算图片数据分割位置
    uint16_t split_index = (height / 2) * width;

    // 绘制上半部分数据
    for (uint16_t byte_index = 0; byte_index < split_index; byte_index++) {
        uint8_t data = bmp_data->dat[byte_index];
        for (uint8_t bit = 0; bit < 8; bit++) {
            uint8_t x_pos = x + (byte_index % width);
            uint8_t y_pos = y + (byte_index / width) * 8 + bit;
            
            uint8_t mode = (data >> bit) & 0x01;  // 提取每个位的值
            
            OLED_DrawPoint(x_pos, y_pos, mode);
        }
    }

    // 绘制下半部分数据
    for (uint16_t byte_index = split_index; byte_index < sizeof(bmp_data->dat); byte_index++) {
        uint8_t data = bmp_data->dat[byte_index];
        for (uint8_t bit = 0; bit < 8; bit++) {
            uint8_t x_pos = x + (byte_index % width);
            uint8_t y_pos = y + (byte_index / width) * 8 + bit + (height / 2) * 8;
            
            uint8_t mode = (data >> bit) & 0x01;  // 提取每个位的值
            
            OLED_DrawPoint(x_pos, y_pos, mode);
        }
    }
//			OLED_Refresh();
} 

/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP1(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const char* name) {
    // 查找BMP数据
    const picture* bmp_data = NULL;
    for (int i = 0; i < sizeof(BMP) / sizeof(picture); i++) {
        if (strcmp(BMP[i].name, name) == 0) {
            bmp_data = &BMP[i];
            break;
        }
    }
    
    if (bmp_data == NULL) {
        return;  // 找不到对应的BMP数据
    }

    // 计算图片的宽度和高度
    uint8_t width = x1 - x0 + 1;
    uint8_t height = y1 - y0 + 1;

     // 计算图片数据分割位置
    uint16_t split_index = ((height + 1) / 2) * width;


    // 绘制上半部分数据
    for (uint16_t byte_index = 0; byte_index < split_index; byte_index++) {
        uint8_t data = bmp_data->dat[byte_index];
        for (uint8_t bit = 0; bit < 8; bit++) {
            uint8_t x_pos = x0 + (byte_index % width);
            uint8_t y_pos = y0 + (byte_index / width) * 8 + bit;
            
            uint8_t mode = (data >> bit) & 0x01;  // 提取每个位的值
            
            OLED_DrawPoint(x_pos, y_pos, mode);
        }
    }

    // 绘制下半部分数据
    for (uint16_t byte_index = split_index; byte_index < sizeof(bmp_data->dat); byte_index++) {
        uint8_t data = bmp_data->dat[byte_index];
        for (uint8_t bit = 0; bit < 8; bit++) {
            uint8_t x_pos = x0 + (byte_index % width);
            uint8_t y_pos = y0 + (byte_index / width) * 8 + bit + (height / 2) * 8;
            
            uint8_t mode = (data >> bit) & 0x01;  // 提取每个位的值
            
            OLED_DrawPoint(x_pos, y_pos, mode);
        }
    }
		  OLED_Refresh();
}
/*********************************************************************
 * @fn      OLED_Init
 *
 * @brief   ??'??OLED
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Init(void)
{
    OLED_CS_L();

    OLED_RST_L();
    HAL_Delay(200);
    OLED_RST_H();

    OLED_WriteByte(0xAE,OLED_CMD); //??????

    OLED_WriteByte(0xD5,OLED_CMD); //?????????????,?????
    OLED_WriteByte(0x80,OLED_CMD);   //[3:0],???????;[7:4],?????

    OLED_WriteByte(0xA8,OLED_CMD); //????????�??
    OLED_WriteByte(0X3F,OLED_CMD); //I??0X3F(1/64)

    OLED_WriteByte(0xD3,OLED_CMD); //???????t??
    OLED_WriteByte(0X00,OLED_CMD); //I???0

    OLED_WriteByte(0x40,OLED_CMD); //?????????'?? [5:0],????.

    OLED_WriteByte(0x8D,OLED_CMD); //????????
    OLED_WriteByte(0x14,OLED_CMD); //bit2??????/???

    OLED_WriteByte(0x20,OLED_CMD); //?????????g?
    OLED_WriteByte(0x01,OLED_CMD); //[1:0],00??????g?;01??????g?;10,????g?;I??10;

    OLED_WriteByte(0x21,OLED_CMD);//????????
    OLED_WriteByte(0x00,OLED_CMD);
    OLED_WriteByte(0x7f,OLED_CMD);

    OLED_WriteByte(0x22,OLED_CMD);//????????
    OLED_WriteByte(0x00,OLED_CMD);
    OLED_WriteByte(0x07,OLED_CMD);

    OLED_WriteByte(0xA1,OLED_CMD); //???????????,bit0: 0,0->0;1,0->127;

    OLED_WriteByte(0xC0,OLED_CMD); //????COM?????;bit3: 0,???g?;1,?????g? COM[N-1]->COM0;N:????�??

    OLED_WriteByte(0xDA,OLED_CMD); //????COM???????????
    OLED_WriteByte(0x12,OLED_CMD); //[5:4]????

    OLED_WriteByte(0x81,OLED_CMD); //????????
    OLED_WriteByte(0xEF,OLED_CMD); //1~255;I??0X7F (????????,??????)

    OLED_WriteByte(0xD9,OLED_CMD); //????????????
    OLED_WriteByte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;

    OLED_WriteByte(0xDB,OLED_CMD); //????VCOMH ???????
    OLED_WriteByte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

    OLED_WriteByte(0xA4,OLED_CMD); //??????????;bit0:1,????;0,???;(????/????)

    OLED_WriteByte(0xA6,OLED_CMD); //??????????;bit0:1,???????;0,???????

    OLED_WriteByte(0xAF,OLED_CMD); //???????

    OLED_Clear();
}

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

oled.h

#ifndef HARDWARE_OLED_H_
#define HARDWARE_OLED_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "main.h"

 * @fn      OLED_DisplayOn
 *
 * @brief   ????OLED???
 *
 * @param   none
 *
 * @return  none
 */
void OLED_DisplayOn(void);

/*********************************************************************
 * @fn      OLED_DisplayOn
 *
 * @brief   ???OLED???
 *
 * @param   none
 *
 * @return  none
 */
void OLED_DisplayOff(void);

/*********************************************************************
 * @fn      OLED_Refresh
 *
 * @brief   ???OLED
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Refresh(void);

/*********************************************************************
 * @fn      OLED_Clear
 *
 * @brief   ????
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Clear(void);

/*********************************************************************
 * @fn      OLED_Fill
 *
 * @brief   ???????K??????
 *
 * @param   x1,y1,x2,y2 - ???????????
 *          mode - 0:???; 1:???
 *
 * @return  none
 */
void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode);

/*********************************************************************
 * @fn      OLED_ShowChar
 *
 * @brief   ???????????h?????,?????????????
 *
 * @param   x    - 0 ~ 127
 *          y    - 0 ~ 63
 *          char - ASC2???
 *          size - ??????: 12/16/24
 *          mode - 0:???????; 1:???????
 *
 * @return  none
 */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode);

/*********************************************************************
 * @fn      OLED_ShowNum
 *
 * @brief   ???????????
 *
 * @param   x??y - ???????
 *          num  - ???
 *          len  - ???????
 *          size - ??????: 12/16/24
 *
 * @return  none
 */
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size);

/*********************************************************************
 * @fn      OLED_ShowString
 *
 * @brief   ????????????????
 *
 * @param   x??y   - ???????
 *          *pChar - ???????'???
 *          size - ??????: 12/16/24
 *
 * @return  none
 */
void OLED_ShowString(uint8_t x, uint8_t y,uint8_t *pChar, uint8_t size1,uint8_t mode);
void OLED_WR_Byte(uint8_t dat,uint8_t cmd);
 void OLED_Set_Pos(unsigned char x, unsigned char y);
 void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode);
 void OLED_DrawBMP(uint8_t x, uint8_t y, const char* name);
 void OLED_DrawBMP1(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const char* name);
/*********************************************************************
 * @fn      OLED_Init
 *
 * @brief   ??'??OLED
 *
 * @param   none
 *
 * @return  none
 */
void OLED_Init(void);

#define OLED_WIDTH 128
#define OLED_HEIGHT 64
/*********************************************************************
*********************************************************************/

#ifdef __cplusplus
}
#endif

#endif /* HARDWARE_OLED_H_ */

main.c

三、运行效果

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值