u8g2 使用IIC驱动uc1617 lcd 字符显示只显示上半部分,不显示下半部

使用u8g2 使用硬件iic驱动某些page为4个字节 带灰度的lcd显示屏幕的时候有时候只显示上半部,下半部不显示,例如uc1617等。

原因:

以uc1617为例,链接https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_uc1617.c

在u8x8_d_uc1617_common方法中的case U8X8_MSG_DISPLAY_DRAW_TILE分支

uint8_t u8x8_d_uc1617_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t x, y, c, a;
  uint8_t *ptr;
  switch(msg)
  {
    case U8X8_MSG_DISPLAY_DRAW_TILE:
      u8x8_cad_StartTransfer(u8x8);
    


      y = ((u8x8_tile_t *)arg_ptr)->y_pos;
      y*=2;

      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
      x *= 8;
      x += u8x8->x_offset;
      u8x8_cad_SendCmd(u8x8, 0x060 | (x&15));
      u8x8_cad_SendCmd(u8x8, 0x070 | (x>>4)); 
      u8x8_cad_SendCmd(u8x8, 0x00 | (y));

#ifdef NOT_REQUIRED
      u8x8_cad_SendCmd(u8x8, 0xf8 );	/* disable window */
      u8x8_cad_SendCmd(u8x8, 0xf4 );	/* page start */
      u8x8_cad_SendCmd(u8x8, y );	
      u8x8_cad_SendCmd(u8x8, 0xf5 );	/* x start */
      u8x8_cad_SendCmd(u8x8, x );	
      u8x8_cad_SendCmd(u8x8, 0xf6 );	/* page end */
      u8x8_cad_SendCmd(u8x8, y );	
      u8x8_cad_SendCmd(u8x8, 0xf7 );	/* x end */
      u8x8_cad_SendCmd(u8x8, 127 );	
      u8x8_cad_SendCmd(u8x8, 0xf9 );	/* enable window  */
#endif

      a = arg_int;
      do
      {
	c = ((u8x8_tile_t *)arg_ptr)->cnt;
	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
	do
	{
	  u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_uc1617_lower4bit(ptr));
	  ptr += 8;
	  x += 8;
	  c--;
	} while( c > 0 );	
	a--;
      } while( a > 0 );

      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
      x *= 8;
      x += u8x8->x_offset;
      u8x8_cad_SendCmd(u8x8, 0x060 | (x&15));
      u8x8_cad_SendCmd(u8x8, 0x070 | (x>>4));    
      u8x8_cad_SendCmd(u8x8, 0x00 | (y+1));
      a = arg_int;
      do
      {
	c = ((u8x8_tile_t *)arg_ptr)->cnt;
	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
	do
	{
	  u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_uc1617_upper4bit(ptr));
	  ptr += 8;
	  x += 8;
	  c--;
	} while( c > 0 );	
	a--;
      } while( a > 0 );
          
      u8x8_cad_EndTransfer(u8x8);
      break;
    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
      if ( arg_int == 0 )
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave0_seq);
      else
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave1_seq);
      break;
    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
      if ( arg_int == 0 )
      {
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip0_seq);
	u8x8->x_offset = u8x8->display_info->default_x_offset;
      }
      else
      {
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip1_seq);
	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
      }	
      break;
#ifdef U8X8_WITH_SET_CONTRAST
    case U8X8_MSG_DISPLAY_SET_CONTRAST:
      u8x8_cad_StartTransfer(u8x8);
      u8x8_cad_SendCmd(u8x8, 0x081 );
      u8x8_cad_SendArg(u8x8, arg_int  );	/* uc1617 has range from 0 to 255 */
      u8x8_cad_EndTransfer(u8x8);
      break;
#endif
    default:
      return 0;
  }
  return 1;
}

在往lcd显示屏写写数据的时候,先用命令写显示地址,再写数据,命令和数据的区别在于iic地址不同,例如写命令使用iic地址0x78,写数据使用iic地址0x79,具体根据不同lcd数据手册iic地址有所不同。上面的分支U8X8_MSG_DISPLAY_DRAW_TILE作用是向lcd先写地址,再写数据,在这个分支中,只有一个u8x8_cad_StartTransfer与u8x8_cad_EndTransfer包含整个方法。

u8x8_cad_EndTransfer用于产生一个iic终止信号,代表操作完成

而在这个方法中,有2个写不同iic地址的行为,但是只产生了一个终止信号,导致可能后半部分无效,所以只显示半面。

解决方案:

添加多个u8x8_cad_StartTransfer与u8x8_cad_EndTransfer。

把对一个地址的操作行为用u8x8_cad_StartTransfer与u8x8_cad_EndTransfer包含起来

例如:

uint8_t u8x8_d_uc1617_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t x, y, c, a;
  uint8_t *ptr;
  switch(msg)
  {
    case U8X8_MSG_DISPLAY_DRAW_TILE:
      u8x8_cad_StartTransfer(u8x8);
    


      y = ((u8x8_tile_t *)arg_ptr)->y_pos;
      y*=2;

      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
      x *= 8;
      x += u8x8->x_offset;
      u8x8_cad_SendCmd(u8x8, 0x060 | (x&15));
      u8x8_cad_SendCmd(u8x8, 0x070 | (x>>4)); 
      u8x8_cad_SendCmd(u8x8, 0x00 | (y));

#ifdef NOT_REQUIRED
      u8x8_cad_SendCmd(u8x8, 0xf8 );	/* disable window */
      u8x8_cad_SendCmd(u8x8, 0xf4 );	/* page start */
      u8x8_cad_SendCmd(u8x8, y );	
      u8x8_cad_SendCmd(u8x8, 0xf5 );	/* x start */
      u8x8_cad_SendCmd(u8x8, x );	
      u8x8_cad_SendCmd(u8x8, 0xf6 );	/* page end */
      u8x8_cad_SendCmd(u8x8, y );	
      u8x8_cad_SendCmd(u8x8, 0xf7 );	/* x end */
      u8x8_cad_SendCmd(u8x8, 127 );	
      u8x8_cad_SendCmd(u8x8, 0xf9 );	/* enable window  */
#endif

      a = arg_int;
      do
      {
	c = ((u8x8_tile_t *)arg_ptr)->cnt;
	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
	do
	{
	  u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_uc1617_lower4bit(ptr));
	  ptr += 8;
	  x += 8;
	  c--;
	} while( c > 0 );	
	a--;

      } while( a > 0 );
// 下面这2行是添加的
u8x8_cad_EndTransfer(u8x8);
u8x8_cad_StartTransfer(u8x8);

      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
      x *= 8;
      x += u8x8->x_offset;
      u8x8_cad_SendCmd(u8x8, 0x060 | (x&15));
      u8x8_cad_SendCmd(u8x8, 0x070 | (x>>4));    
      u8x8_cad_SendCmd(u8x8, 0x00 | (y+1));
      a = arg_int;
      do
      {
	c = ((u8x8_tile_t *)arg_ptr)->cnt;
	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
	do
	{
	  u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_uc1617_upper4bit(ptr));
	  ptr += 8;
	  x += 8;
	  c--;
	} while( c > 0 );	
	a--;
      } while( a > 0 );
          
      u8x8_cad_EndTransfer(u8x8);
      break;
    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
      if ( arg_int == 0 )
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave0_seq);
      else
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave1_seq);
      break;
    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
      if ( arg_int == 0 )
      {
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip0_seq);
	u8x8->x_offset = u8x8->display_info->default_x_offset;
      }
      else
      {
	u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip1_seq);
	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
      }	
      break;
#ifdef U8X8_WITH_SET_CONTRAST
    case U8X8_MSG_DISPLAY_SET_CONTRAST:
      u8x8_cad_StartTransfer(u8x8);
      u8x8_cad_SendCmd(u8x8, 0x081 );
      u8x8_cad_SendArg(u8x8, arg_int  );	/* uc1617 has range from 0 to 255 */
      u8x8_cad_EndTransfer(u8x8);
      break;
#endif
    default:
      return 0;
  }
  return 1;
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值