LED单元板驱动(HUB75接口)

开始之前先吐槽一下,搜这个的资料。要么都是Arduino,要么单片机的收费。小小的一个LED单元板,凭什么?

用Arduino是你速度快还是我ST,树莓派不好用?收费更离谱,这点东西还藏私?给你个中指凸。把原理都写出来看你怎么收费。

 

一、接口定义及原理

如图,有两个RGB通道,共占用6个IO。剩下的ABCDE为地址通道,LAT为行数据锁存通道,CLK为数据时钟,OE为低电平使能LED显示。图片这里没有E,证明它是16扫的,有E就会把B上面的地改为E。这样就是5位,2的5次方32扫。16扫控制16行显示,共2个RGB通道所以16扫可以控制16*2=32行显示。

(1)单元板的显示为单位时间内显示一行数据,然后短时间内切换到另一行显示,16扫一个显示周期为切换16次。

(2)两个RGB通道分别控制上下两部分的RGB灯。图片中的为32*16。正常来说,需要3个地址ABC,假设ABC 3个IO为高电平意味着选定第7行跟第15行,RGB1通道数据被写到第7行,RGB2数据被写到第15行。(我这个板子比较坑,有点不同)

(3)数据的写入顺序,失能LED显示,写入一行数据,选定行,锁存,使能LED显示。

(4)颜色渐变,方法是同一行扫描32次,假设R1我只显示一次,那它占空比就是1/32,显示次数越多越来亮。

         这方法挺麻烦,但暂时没想到别的方法。

 

  By the way:我这板子比较奇怪,数据写入方式跟一般的板子不一样。具体看图:

  

数据填充的时候,RBG1通道前8个时钟周期数据在第0行,接下来8个时钟周期数据却跳到第4行去了。然后又跳回第一行。

正常的应该是一直往同一行填充数据才对的。所以我买的这个板子比较奇葩。

 

二、驱动代码

使用单片机为STM32F407VE,STM32CUBEMX生成代码

#include "main.h"
#include "tim.h"
#include "gpio.h"

void SystemClock_Config(void);

#define OE_H   HAL_GPIO_WritePin(OE_GPIO_Port,OE_Pin,GPIO_PIN_SET)
#define R1_H   HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_SET)
#define R2_H   HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_SET)
#define G1_H   HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_SET)
#define G2_H   HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_SET)
#define B1_H   HAL_GPIO_WritePin(B1_GPIO_Port,B1_Pin,GPIO_PIN_SET)
#define B2_H   HAL_GPIO_WritePin(B2_GPIO_Port,B2_Pin,GPIO_PIN_SET)
#define A_H    HAL_GPIO_WritePin(A_GPIO_Port,A_Pin,GPIO_PIN_SET)
#define B_H    HAL_GPIO_WritePin(B_GPIO_Port,B_Pin,GPIO_PIN_SET)
#define CLK_H  HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET)
#define LAT_H  HAL_GPIO_WritePin(LAT_GPIO_Port,LAT_Pin,GPIO_PIN_SET)

#define OE_L   HAL_GPIO_WritePin(OE_GPIO_Port,OE_Pin,GPIO_PIN_RESET)
#define R1_L   HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET)
#define R2_L   HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET)
#define G1_L   HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET)
#define G2_L   HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET)
#define B1_L   HAL_GPIO_WritePin(B1_GPIO_Port,B1_Pin,GPIO_PIN_RESET)
#define B2_L   HAL_GPIO_WritePin(B2_GPIO_Port,B2_Pin,GPIO_PIN_RESET)
#define A_L    HAL_GPIO_WritePin(A_GPIO_Port,A_Pin,GPIO_PIN_RESET)
#define B_L    HAL_GPIO_WritePin(B_GPIO_Port,B_Pin,GPIO_PIN_RESET)
#define CLK_L  HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET)
#define LAT_L  HAL_GPIO_WritePin(LAT_GPIO_Port,LAT_Pin,GPIO_PIN_RESET)

//此单元板4扫一次性输入2行数据,2个通道,故控制2*2*LED_ROW=16行
#define LED_ROW      4
//一行32个点
#define LED_COLUMN   32

typedef struct
{
	uint16_t B:5;
	uint16_t G:5;
	uint16_t R:5;	
	uint16_t null:1;		
}led_data;


extern const unsigned char gImage_111[1024];
led_data *img_data = (led_data*)gImage_111;



void delay(uint16_t time)
{
  uint16_t i,j;
	
  for(i=0;i<time;i++)
    for(j=0;j<100;j++);	  
}



void led_DRamDis(led_data *pdata)
{
	  uint16_t col_depth;
	  uint16_t j,k,l;
	  uint16_t row=0;
	  uint16_t pos_down = LED_COLUMN*LED_ROW*2;  //指向LED下半部分数据起点

          if(pdata == NULL) return;

	  for(row = 0;row<LED_ROW;row++)  //发送一扫数据
	  {
		for(col_depth=0;col_depth<32;col_depth++) //每种颜色5bit,32种变化
               {
		 OE_H;
				
		 for(l=0;l<4;l++)   //一行4*8像素点数据
		 {		
			for(k=0;k<2;k++)  //发送16像素点数据后,数据被续写
			{
				for(j=0;j<8;j++)   //发送8像素点数据后数据会跳转
				{           

					if(col_depth<pdata[j+row*32+32*LED_ROW*k+l*8].B) B1_H; 
					else                                             B1_L; 
					if(col_depth<pdata[j+row*32+32*LED_ROW*k+l*8].R) R1_H; 
					else                                             R1_L; 
					if(col_depth<pdata[j+row*32+32*LED_ROW*k+l*8].G) G1_H; 
					else                                             G1_L; 
					if(col_depth<pdata[j+row*32+pos_down+32*LED_ROW*k+l*8].B) B2_H; 
					else                                                      B2_L; 
					if(col_depth<pdata[j+row*32+pos_down+32*LED_ROW*k+l*8].R) R2_H; 
					else                                                      R2_L; 
								
					if(col_depth<pdata[j+row*32+pos_down+32*LED_ROW*k+l*8].G) G2_H; 
					else                                                      G2_L; 	
								
					CLK_L;
					CLK_H;			
				}					
			}
		}

		//使能一行数据
		if(row&0x01) A_H;
		else         A_L;
					
		if(row&0x02) B_H;
		else         B_L;

					
		LAT_L;
		LAT_H;         
		OE_L;	
		delay(10); //短暂延时,让当前行数据显示一段时间
					
	}				
				
  }		
}


led_data img_data2[512];

void RedDis(uint8_t r)
{
  uint16_t i;

  for(i=0;i<512;i++)
  {
    img_data2[i].R = r;
    img_data2[i].G = 0;
    img_data2[i].B = 0;			
  }

  for(i=0;i<5;i++)
    led_DRamDis(img_data2);
}

void BlueDis(uint8_t b)
{
  uint16_t i;

  for(i=0;i<512;i++)
  {
    img_data2[i].R = 0;
    img_data2[i].G = 0;
    img_data2[i].B = b;			
  }

  for(i=0;i<5;i++)
    led_DRamDis(img_data2);
}

void GreenDis(uint8_t g)
{
  uint16_t i;

  for(i=0;i<512;i++)
  {
    img_data2[i].R = 0;
    img_data2[i].G = g;
    img_data2[i].B = 0;			
  }

  for(i=0;i<5;i++)
    led_DRamDis(img_data2);
}


int main(void)
{
  uint16_t i;
  uint16_t *p;
 
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM7_Init();

  while (1)
  {
    for(i=0;i<16;i++)
      RedDis(i);		
    for(i=0;i<16;i++)
      BlueDis(i);	
    for(i=0;i<16;i++)
      GreenDis(i);			
	
    for(i=0;i<100;i++)
      led_DRamDis(img_data);
  }
}


void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{

}

图像数据数组采用Image2Lcd 2.9生成,搞单片机的人应该对此很熟悉。16位RBG555数据格式

const unsigned char gImage_111[1024] = { /* 0X00,0X10,0X20,0X00,0X10,0X00,0X00,0X1B, */
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XC9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE8,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XCA,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC8,0X03,
0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XC9,0X03,0XC8,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XEA,0X03,
0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XC9,0X03,0X00,0X7C,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XFF,0X7F,0XFF,0X7F,0XFF,0X7F,0XFF,0X7F,0XE9,0X03,
0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0X00,0X7C,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0X1F,0X00,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,
0XE9,0X03,0XFF,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XE9,0X03,
0XC9,0X03,0XE0,0X7F,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0X00,0X7C,0XC9,0X03,0X00,0X7C,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0X1F,0X00,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,
0XFF,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XC9,0X03,
0XC9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE0,0X7F,0XE9,0X03,
0XC9,0X03,0XE9,0X03,0X00,0X7C,0XC9,0X03,0X00,0X7C,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0X1F,0X00,0XE9,0X03,0XE9,0X03,0XC9,0X03,0X1F,0X00,0XE9,0X03,0XC9,0X03,
0XFF,0X7F,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE0,0X7F,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0X00,0X7C,0XE9,0X03,0X00,0X7C,0XC9,0X03,0XC9,0X03,0XE9,0X03,
0XC9,0X03,0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XFF,0X7F,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE0,0X7F,0XC9,0X03,
0XE9,0X03,0XE9,0X03,0X00,0X7C,0XC9,0X03,0X00,0X7C,0XC9,0X03,0XE9,0X03,0XC9,0X03,
0XE9,0X03,0X1F,0X00,0XC9,0X03,0XC9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,0XE9,0X03,
0XFF,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE0,0X7F,0XC9,0X03,
0XE9,0X03,0X00,0X7C,0X00,0X7C,0X00,0X7C,0X00,0X7C,0X00,0X7C,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0X1F,0X00,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,
0XFF,0X7F,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE0,0X7F,0XE9,0X03,
0XC9,0X03,0X00,0X7C,0XE9,0X03,0XC9,0X03,0XE9,0X03,0X00,0X7C,0XE9,0X03,0XC9,0X03,
0XC9,0X03,0X1F,0X00,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,
0XFF,0X7F,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XE9,0X03,
0XC9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE0,0X7F,0XE9,0X03,
0XE9,0X03,0X00,0X7C,0XE9,0X03,0XE9,0X03,0XE9,0X03,0X00,0X7C,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0X1F,0X00,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0X1F,0X00,0XE9,0X03,
0XE9,0X03,0XFF,0X7F,0XEA,0X03,0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XC8,0X03,0XE9,0X03,
0XC9,0X03,0XE0,0X7F,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE0,0X7F,0XE9,0X03,0XE9,0X03,
0X00,0X7C,0X00,0X7C,0X00,0X7C,0XE9,0X03,0X00,0X7C,0X00,0X7C,0X00,0X7C,0XC9,0X03,
0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0X1F,0X00,0XC9,0X03,0XC9,0X03,
0XE9,0X03,0XE9,0X03,0XFF,0X7F,0XFF,0X7F,0XFF,0X7F,0XE9,0X03,0XE9,0X03,0XC9,0X03,
0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE0,0X7F,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
0XC9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XC9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC8,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,
0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XC9,0X03,
0XE9,0X03,0XC9,0X03,0XE9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,0XC9,0X03,0XE9,0X03,
};

 

三、效果图

       改变每个RGB通道的占空比实现渐变(一行扫描32次),所以闪烁会严重些。

 

 

 

### 关于STM32驱动HUB75 LED面板 在使用STM32作为低级驱动器来控制基于HUB75接口LED矩阵时,通常涉及多个硬件信号线以及复杂的时序管理。具体来说,HUB75是一种用于RGB LED显示屏的标准接口协议,它通过多条数据线并行传输红、绿、蓝三种颜色的数据,并配合同步信号完成像素刷新。 #### 主要功能模块 1. **GPIO配置**: 需要在STM32上分配足够的GPIO引脚以匹配HUB75所需的信号数量。这些信号一般包括CLK(时钟)、R1/G1/B1/R2/G2/B2(两组RGB数据)、OE(输出使能)和LAT(锁存)。对于较大的显示区域,可能还需要链式扩展支持更多的行扫描[^1]。 2. **DMA与定时器协同工作**: 实现高效的帧缓冲区更新机制非常重要。可以利用STM32内部的DMA控制器自动处理大量连续写入操作到指定端口寄存器中去减少CPU负载;同时借助高级外设总线上的通用计数器产生精确周期性的中断事件触发新一轮图像绘制流程。 3. **软件架构设计**: - 应用层负责接收来自网络或其他输入源的艺术网(Art-Net)包解析后的最终渲染目标图案信息; - 中间件部分承担色彩转换计算任务比如gamma校正等功能实现最佳视觉效果呈现; - 而底层则专注于实际物理层面的具体动作执行如前所述各项参数设定等等. 下面给出一段简化版伪代码展示如何初始化相关资源及基本绘图逻辑: ```c #include "stm32f4xx_hal.h" // 定义全局变量存储当前屏幕状态 uint8_t screenBuffer[NUM_ROWS][NUM_COLS * BYTES_PER_PIXEL]; void Init_Hub75(void){ // 初始化 GPIOs 对应 HUB75 的各个管脚 } void Send_Row(uint8_t row_index){ // 设置 OE 和 LAT 以便选通特定的一行 HAL_GPIO_WritePin(OE_PORT, OE_PIN, GPIO_RESET); for(int col=0;col<NUM_COLS*BYTES_PER_PIXEL;col++){ uint8_t pixelValue = screenBuffer[row_index][col]; // 将pixelValue拆分为独立的颜色分量并通过相应通道发送出去 SetColorData(R1_CHANNEL, (pixelValue >> RED_SHIFT) & MASK); SetColorData(G1_CHANNEL, (pixelValue >> GREEN_SHIFT)& MASK); SetColorData(B1_CHANNEL, (pixelValue >> BLUE_SHIFT)& MASK); // 发送下一个字节前推进一位时钟脉冲 ToggleClock(); } HAL_GPIO_WritePin(LAT_PORT, LAT_PIN, GPIO_SET); DelayMicroseconds(LOCK_TIME_US); // 等待足够长时间让锁存生效 HAL_GPIO_WritePin(LAT_PORT, LAT_PIN, GPIO_RESET); } ``` 上述仅为概念演示用途,在真实环境中还需考虑诸多细节因素诸如抗干扰措施优化功耗表现等方面内容未在此详尽列举出来。
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值