对于用硬件SPI控制的方法,网上已经有很多资料了,我也是查看网上的资料重新进行了封装,主要遇到一个第一个灯始终无法控制问题。
首先感谢作者提供的思路和方法。
1.控制思路请看这一篇
2.代码的实现请看这一篇
https://blog.csdn.net/weixin_43572492/article/details/89632893
其中使用代码的实现后发现第一个灯时钟没法控制。后来发现了把复位指令直接放到每一次数据发送完成后,再发送一次就可以了。
我的代码实现如下,使用的STM32 HAL库
主要是封装了控制代码,如下实现了红、绿每500ms变化一次
//一般SPI速率控制在6.5MHz就能达到每个字节1.25us左右
#define CODE0 0xC0
#define CODE1 0xF8
#define LED_COUNT_NUM 10 //灯的总长度
//100次,
const uint8_t LedsArrayRest[100] = {0};
uint8_t LedsArray[LED_COUNT_NUM * 24];
int16_t LedsCount = 0;
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void WS2811_Set_RGB(uint8_t r,uint8_t g, uint8_t b, uint16_t len)
{
//清除掉所有数据
memset(LedsArray,0,len * 24);
//添加数据进入到发送数组
for(uint16_t i = 0; i < len; i ++)
{
//红
for(int8_t j = 7; j >= 0; j--)
{
if((r & (1<<j)) == 0)
{
LedsArray[LedsCount++] = CODE0;
}
else
{
LedsArray[LedsCount++] = CODE1;
}
}
//绿
for(int8_t j = 7; j >= 0; j--)
{
if((g & (1<<j)) == 0)
{
LedsArray[LedsCount++] = CODE0;
}
else
{
LedsArray[LedsCount++] = CODE1;
}
}
//蓝
for(int8_t j = 7; j >= 0; j--)
{
if((b & (1<<j)) == 0)
{
LedsArray[LedsCount++] = CODE0;
}
else
{
LedsArray[LedsCount++] = CODE1;
}
}
}
HAL_SPI_Transmit_DMA(&hspi1, LedsArray, LedsCount);
LedsCount = 0;
while(!(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_READY));
//发送完成后一定要发送一次复位,不然会第一个灯无法控制
HAL_SPI_Transmit_DMA(&hspi1, LedsArrayRest, 100);
while(!(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_READY));
}
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
WS2811_Set_RGB(100,0,0,8);
HAL_Delay(500);
WS2811_Set_RGB(0,100,0,8);
HAL_Delay(500);
}
//一般SPI速率控制在6.5MHz就能达到每个字节1.25us左右
SPI配置如下
时钟频率:这里没用最大的72M,使用48M,然后SPI分频可以得到接近6.4MHZ的频率,这样比较接近1.25us的时序。
以上参考链接如有侵权,麻烦作者告知,本人立即处理,谢谢理解。