1352|7

58

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【HC32F448测评】SPI学习与SPI软/硬件驱动OLED [复制链接]

 
  1. 模拟SPI驱动OLED:
    宏定义:
    
    #define CS2_PORT        (GPIO_PORT_D)
    #define CS2_PIN         (GPIO_PIN_00)
    
    #define DC2_PORT				 GPIO_PORT_D
    #define DC2_PIN					 GPIO_PIN_01
    
    #define RST2_PORT				 GPIO_PORT_D
    #define RST2_PIN				 GPIO_PIN_02
    
    /* MOSI */
    #define SDIN_PORT        (GPIO_PORT_D)
    #define SDIN_PIN        (GPIO_PIN_08)
    
    /*SCK*/
    #define SCK2_PORT         (GPIO_PORT_D)
    #define SCK2_PIN          (GPIO_PIN_09)
    
    #define OLED_RST_Clr() 	GPIO_ResetPins(RST2_PORT, RST2_PIN)//RES
    #define OLED_RST_Set() 	GPIO_SetPins(RST2_PORT, RST2_PIN)
     
    #define OLED_DC_Clr() 	GPIO_ResetPins(DC2_PORT, DC2_PIN)//DC
    #define OLED_DC_Set() 	GPIO_SetPins(DC2_PORT, DC2_PIN)
     		     
    #define OLED_CS_Clr()   GPIO_ResetPins(CS2_PORT, CS2_PIN)//CS
    #define OLED_CS_Set()   GPIO_SetPins(CS2_PORT, CS2_PIN)
    
    #define OLED_SCLK_Clr()  GPIO_ResetPins(SCK2_PORT, SCK2_PIN)//CS
    #define OLED_SCLK_Set()  GPIO_SetPins(SCK2_PORT, SCK2_PIN)
     
    #define OLED_SDIN_Clr()  GPIO_ResetPins(SDIN_PORT, SDIN_PIN)//CS
    #define OLED_SDIN_Set()  GPIO_SetPins(SDIN_PORT, SDIN_PIN)
    
    
    
     

    OLED.c中初始化GPIO口的函数,初始化模拟SPI,只需要把PIN口设置为输出即可。另外还有一个写入字节的函数,拉低DC输入cmd,拉高DC输入data。

  2.  

    //初始化SSD1306					    
    void OLED_Init(void)
    { 	
    	stc_gpio_init_t stcGpioInit;
    	
    		(void)GPIO_StructInit(&stcGpioInit);
    		stcGpioInit.u16PinDir = PIN_DIR_OUT;
    	
    		(void)GPIO_Init(RST2_PORT, RST2_PIN	, &stcGpioInit);
    		(void)GPIO_Init(DC2_PORT, DC2_PIN	,  &stcGpioInit);
    		(void)GPIO_Init(CS2_PORT,   CS2_PIN,   &stcGpioInit);
        (void)GPIO_Init(SCK2_PORT,  SCK2_PIN,  &stcGpioInit);
        (void)GPIO_Init(SDIN_PORT , SDIN_PIN, &stcGpioInit);
    
     
      OLED_RST_Set();
    	DDL_DelayMS(100);
    	OLED_RST_Clr();
    	DDL_DelayMS(200);
    	OLED_RST_Set(); 
    
    	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
    	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
    	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
    	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    
    	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
    	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
    	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
    	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
    
    	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
    	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
    	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
    	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
    	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
    	OLED_WR_Byte(0x12,OLED_CMD);
    
    	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
    	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
    	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    	OLED_WR_Byte(0x02,OLED_CMD);//
    
    	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
    	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
    
    	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
    	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
    
    	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 
    	OLED_Clear();
    
    	OLED_Set_Pos(0,0); 	
    
    }  
    
     //向SSD1306写入一个字节。
    //dat:要写入的数据/命令
    //cmd:数据/命令标志 0,表示命令;1,表示数据;
    void OLED_WR_Byte(u8 dat,u8 cmd)
    {	
    	u8 i;			  
    	if(cmd)
    	  OLED_DC_Set();
    	else 
    	  OLED_DC_Clr();		  
    	OLED_CS_Clr();
    	for(i=0;i<8;i++)
    	{			  
    		OLED_SCLK_Clr();
    		if(dat&0x80)
    		   OLED_SDIN_Set();
    		else 
    		   OLED_SDIN_Clr();
    		OLED_SCLK_Set();
    		dat<<=1;   
    	}				 		  
    	OLED_CS_Set();
    	OLED_DC_Set();   	  
    } 

    oled其余函数,如果需要oledfont去我关于I2C的帖子里的zip包下载。
     

    
    	void OLED_Set_Pos(unsigned char x, unsigned char y) 
    { 
    	OLED_WR_Byte(0xb0+y,OLED_CMD);
    	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
    	OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD); 
    }   	  
    //开启OLED显示    
    void OLED_Display_On(void)
    {
    	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
    	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
    }
    //关闭OLED显示     
    void OLED_Display_Off(void)
    {
    	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
    	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
    }		   			 
    //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
    void OLED_Clear(void)  
    {  
    	u8 i,n;		    
    	for(i=0;i<8;i++)  
    	{  
    		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
    		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
    		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
    		for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
    	} //更新显示
    }
    
    
    //在指定位置显示一个字符,包括部分字符
    //x:0~127
    //y:0~63
    //mode:0,反白显示;1,正常显示				 
    //size:选择字体 16/12 
    void OLED_ShowChar(u8 x,u8 y,u8 chr)
    {      	
    	unsigned char c=0,i=0;	
    		c=chr-' ';//得到偏移后的值			
    		if(x>Max_Column-1){x=0;y=y+2;}
    		if(SIZE ==16)
    			{
    			OLED_Set_Pos(x,y);	
    			for(i=0;i<8;i++)
    			OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
    			OLED_Set_Pos(x,y+1);
    			for(i=0;i<8;i++)
    			OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
    			}
    			else {	
    				OLED_Set_Pos(x,y+1);
    				for(i=0;i<6;i++)
    				OLED_WR_Byte(F6x8[c][i],OLED_DATA);
    				
    			}
    }
    ////m^n函数
    //u32 oled_pow(u8 m,u8 n)
    //{
    //	u32 result=1;	 
    //	while(n--)result*=m;    
    //	return result;
    //}				  
    //显示2个数字
    //x,y :起点坐标	 
    //len :数字的位数
    //size:字体大小
    //mode:模式	0,填充模式;1,叠加模式
    //num:数值(0~4294967295);	 		  
    void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
    {         	
    	u8 t,temp;
    	u8 enshow=0;						   
    	for(t=0;t<len;t++)
    	{
    		temp=(num/oled_pow(10,len-t-1))%10;
    		if(enshow==0&&t<(len-1))
    		{
    			if(temp==0)
    			{
    				OLED_ShowChar(x+(size/2)*t,y,' ');
    				continue;
    			}else enshow=1; 
    		 	 
    		}
    	 	OLED_ShowChar(x+(size/2)*t,y,temp+'0'); 
    	}
    } 
    //显示一个字符号串
    void OLED_ShowString(u8 x,u8 y,u8 *chr)
    {
    	unsigned char j=0;
    	while (chr[j]!='\0')
    	{		OLED_ShowChar(x,y,chr[j]);
    			x+=8;
    		if(x>120){x=0;y+=2;}
    			j++;
    	}
    }
    //显示汉字
    void OLED_ShowCHinese(u8 x,u8 y,u8 no)
    {      			    
    	u8 t,adder=0;
    	OLED_Set_Pos(x,y);	
        for(t=0;t<16;t++)
    		{
    				OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
    				adder+=1;
         }	
    		OLED_Set_Pos(x,y+1);	
        for(t=0;t<16;t++)
    			{	
    				OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
    				adder+=1;
          }					
    }
    /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
    void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
    { 	
     unsigned int j=0;
     unsigned char x,y;
      
      if(y1%8==0) y=y1/8;      
      else y=y1/8+1;
    	for(y=y0;y<y1;y++)
    	{
    		OLED_Set_Pos(x0,y);
        for(x=x0;x<x1;x++)
    	    {      
    	    	OLED_WR_Byte(BMP[j++],OLED_DATA);	    	
    	    }
    	}
    } 

    2.硬件SPI

    1. 配置SPI
       

      int32_t spiconfig(CM_SPI_TypeDef *SPIx)
      {
      
      	   int32_t i32Ret;
      	   stc_spi_init_t stcspiinit;
      		 stc_spi_delay_t stcSpiDelayCfg;
      	
      	
      		/* Peripheral clock enable */
      		FCG_Fcg1PeriphClockCmd(SPI_CLK, ENABLE);
      			(void)SPI_StructInit(&stcspiinit);
      	  (void)SPI_DelayStructInit(&stcSpiDelayCfg);
      	
      			(void)SPI_DeInit(SPI_UNIT);
      	
          stcspiinit.u32WireMode          = SPI_3_WIRE;
          stcspiinit.u32TransMode         = SPI_FULL_DUPLEX;
          stcspiinit.u32MasterSlave       = SPI_MASTER;
      		stcspiinit.u32ModeFaultDetect   = SPI_MD_FAULT_DETECT_DISABLE;
          stcspiinit.u32Parity            = SPI_PARITY_INVD;
          stcspiinit.u32SpiMode           = SPI_MD_1;
          stcspiinit.u32BaudRatePrescaler = SPI_BR_CLK_DIV16;
          stcspiinit.u32DataBits          = SPI_DATA_SIZE_8BIT;
          stcspiinit.u32FirstBit          = SPI_FIRST_MSB;
          stcspiinit.u32FrameLevel        = SPI_1_FRAME;
       
      		i32Ret=SPI_Init(SPI_UNIT, &stcspiinit);
      //		SPI_SSPinSelect(SPI_UNIT,SPI_PIN_SS0);
      //		SPI_SetCommMode(SPI_UNIT,SPI_COMM_MD_NORMAL);
      //	    stcSpiDelayCfg.u32IntervalDelay = SPI_INTERVAL_TIME_4SCK;
      //    stcSpiDelayCfg.u32ReleaseDelay  = SPI_RELEASE_TIME_4SCK;
      //    stcSpiDelayCfg.u32SetupDelay    = SPI_SETUP_TIME_1SCK;
      //    (void)SPI_DelayTimeConfig(SPI_UNIT, &stcSpiDelayCfg);
      //		
      	
           /* Enable SPI */
           SPI_Cmd(SPI_UNIT, ENABLE);
      		 
      		 SPI_SetSckPhase(SPI_UNIT, SPI_SCK_PHASE_EVEN_EDGE_SAMPLE);
           SPI_SetCommMode(SPI_UNIT, SPI_COMM_MD_CONTINUE);
      	
      	return i32Ret;
      }
      
      void SPIInit(void){
      	stc_gpio_init_t stcGpioInit;
      
          /* Configuration SPI */
      		(void)GPIO_StructInit(&stcGpioInit);
          stcGpioInit.u16PinDrv       = PIN_HIGH_DRV;
      	
      	  (void)GPIO_Init(MISO_PORT,MISO_PIN, &stcGpioInit);
      	
          stcGpioInit.u16PinInputType = PIN_IN_TYPE_CMOS;
      
      
          (void)GPIO_Init(SCK2_PORT,  SCK2_PIN,  &stcGpioInit);
          (void)GPIO_Init(SDIN_PORT , SDIN_PIN, &stcGpioInit);
      	
      		 /* Configure Port */
      //    GPIO_SetFunc(CS_PORT,   CS_PIN,   CS_FUNC);
          GPIO_SetFunc(SCK2_PORT,  SCK2_PIN,  SCK_FUNC);
          GPIO_SetFunc(SDIN_PORT, SDIN_PIN, MOSI_FUNC);
          GPIO_SetFunc(MISO_PORT, MISO_PIN, MISO_FUNC);
      	
      		(void)spiconfig(SPI_UNIT);
      }
    2. 更改oled初始化函数和字节写入函数:
       //向SSD1306写入一个字节。
      //dat:要写入的数据/命令
      //cmd:数据/命令标志 0,表示命令;1,表示数据;
      void OLED_WR_Byte(u8 dat,u8 cmd)
      {	
      	u8 i;			  
      	if(cmd)
      	  OLED_DC_Set();
      	else 
      	  OLED_DC_Clr();		  
      	OLED_CS_Clr();
      //	for(i=0;i<8;i++)
      //	{			  
      //		OLED_SCLK_Clr();
      //		if(dat&0x80)
      //		   OLED_SDIN_Set();
      //		else 
      //		   OLED_SDIN_Clr();
      //		OLED_SCLK_Set();
      //		dat<<=1;   
      //	}				 		  
      	SPI_Trans(SPI_UNIT , &dat, 1, 200);
      	OLED_CS_Set();
      	OLED_DC_Set();   	  
      } 
      
      //初始化SSD1306					    
      void OLED_Init(void)
      { 	
      	stc_gpio_init_t stcGpioInit;
      	
      		(void)GPIO_StructInit(&stcGpioInit);
      		stcGpioInit.u16PinDir = PIN_DIR_OUT;
      	
      		(void)GPIO_Init(RST2_PORT, RST2_PIN	, &stcGpioInit);
      		(void)GPIO_Init(DC2_PORT, DC2_PIN	,  &stcGpioInit);
      		(void)GPIO_Init(CS2_PORT,   CS2_PIN,   &stcGpioInit);
      //    (void)GPIO_Init(SCK2_PORT,  SCK2_PIN,  &stcGpioInit);
      //    (void)GPIO_Init(SDIN_PORT , SDIN_PIN, &stcGpioInit);
      
       
        OLED_RST_Set();
      	DDL_DelayMS(100);
      	OLED_RST_Clr();
      	DDL_DelayMS(200);
      	OLED_RST_Set(); 
      
      	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
      	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
      	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
      	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
      
      	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
      	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
      	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
      	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
      	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
      	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
      	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
      
      	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
      	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
      	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
      	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
      	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
      	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
      	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
      	OLED_WR_Byte(0x12,OLED_CMD);
      
      	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
      	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
      	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
      	OLED_WR_Byte(0x02,OLED_CMD);//
      
      	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
      	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
      
      	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
      	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
      	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
      
      	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 
      	OLED_Clear();
      
      	OLED_Set_Pos(0,0); 	
      
      }  
      
  3. 效果:
     
  4. 问题:上述这个图片是软件模拟得出的,硬件SPI驱动OLED的函数却有问题,第一个就是SPI传输的效率比模拟的还要低,并且OLED没有任何显示,到现在也没有解决问题,问题还在查找中。

最新回复

没有楼主你这么有才,我申请的开发板没有通过,只能静静的给您提建议!   详情 回复 发表于 2023-9-6 09:24
点赞 关注
 
 

回复
举报

6841

帖子

11

TA的资源

版主

沙发
 
跟i2c对比一下,哪个速度快一些,硬件SPI要看一下时序的问题。

点评

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下  详情 回复 发表于 2023-9-5 23:14
 
 
 

回复

9716

帖子

24

TA的资源

版主

板凳
 

硬件不会比模拟慢的 你用示波器看看硬件的波形


点评

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下  详情 回复 发表于 2023-9-5 23:13
 
 
 

回复

160

帖子

5

TA的资源

一粒金砂(中级)

4
 

建议看下波形,算下通信速率

点评

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下  详情 回复 发表于 2023-9-5 23:13
 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(中级)

5
 
littleshrimp 发表于 2023-9-5 12:09 硬件不会比模拟慢的 你用示波器看看硬件的波形

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下

 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(中级)

6
 
烟花绽放 发表于 2023-9-5 18:10 建议看下波形,算下通信速率

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下

 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(中级)

7
 
lugl4313820 发表于 2023-9-3 08:49 跟i2c对比一下,哪个速度快一些,硬件SPI要看一下时序的问题。

最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下

点评

没有楼主你这么有才,我申请的开发板没有通过,只能静静的给您提建议!  详情 回复 发表于 2023-9-6 09:24
 
 
 

回复

6841

帖子

11

TA的资源

版主

8
 
学学学学学学学 发表于 2023-9-5 23:14 最近不在学校不方便找示波器测,大佬要不帮忙小小瞅一下

没有楼主你这么有才,我申请的开发板没有通过,只能静静的给您提建议!

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表