今天我們用STM32G070RB NUCLEO開發(fā)板 和WS2812燈帶制作一個七彩星空燈。
《工作原理》
1,上電時,WS2812數(shù)據(jù)IO為低電平保持。
2,空閑時,IO為低電平。
3,數(shù)據(jù)發(fā)送完畢后,保持電平,超過規(guī)格書上定義的RESET時間(只有低電平時間超過280us,就可以認為是RESET.)
先看下數(shù)據(jù)的時序
如下是每24bit的組成。注意,順序不是RGB888,而是GRB888。一般我們?nèi)☆伾臄?shù)值,都是RGB順序,所以這里在代碼里實現(xiàn)的時候,會需要做一下移位。另外,需要注意的是,需要高位先發(fā)(MSB)。
時序波形圖。關(guān)鍵在于用什么方法去表示Bit的波形,網(wǎng)絡上的方法有很多。例如PWM,也有用SPI。今天我們就先用一種簡單方法實行吧,IO口模擬是不錯的選擇。
《新建工程》
1、萬事從新建工程開始,打開STM32CubeMX
2、在搜索框內(nèi)搜索 我們的開發(fā)板型號,也就是STM32G070RB,好的這樣工程就新建好的,
3、配置時鐘樹,如下圖所示。
4、接下來配置引腳 ,這里我們采用的是PWM+DMA的方式來驅(qū)動WS2812,通過WS2812的手冊可以得知驅(qū)動需要800KHZ的頻率好的我們現(xiàn)在來配置定時器,這里以定時器1為例來配置。如下圖所示。計算方法79=(64M/800K)-1得出。下面的Pulse是指一個周期的脈沖數(shù)
5、下面我們開始配置DMA,如下圖所示配置
6、好的到這里就可以生成代碼
好的到這里我們就已經(jīng)把我們需要用到的資源初始化完成了
《開始寫代碼》
1、打開我們上次教程生成的代碼;我們打開工程,將一下代碼復制到下圖所在位置
uint16_t static RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
2、接下來就是DMA傳輸完成回調(diào)函數(shù)(根據(jù)你使用的定時器配置),以下函數(shù)都復制到main.c 的/* USER CODE BEGIN 4 */代碼區(qū)
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1);
}
3、下面就是今天的最后一步WS2812的驅(qū)動函數(shù)了,以下函數(shù)的作用是根據(jù)WS2812的數(shù)量將燈的GRB顏色數(shù)據(jù)寫到需要DMA傳送的數(shù)組中
void WS281x_SetPixelColor(uint16_t n, uint32_t GRBColor)
{
uint8_t i;
if (n < LED_NUMS)
{
for (i = 0; i < 24; ++i)
RGB_buffur[24 * n + i] = (((GRBColor << i) & 0X800000) ? ONE_PULSE : ZERO_PULSE);
}
}
4、將三個顏色的數(shù)據(jù)合并成GRB數(shù)據(jù)
uint32_t WS281x_Color(uint8_t red, uint8_t green, uint8_t blue)
{
return green << 16 | red << 8 | blue;
}
5、這是一個簡單的顏色漸變算法 ,感興趣的可以研究研究
uint32_t Wheel(uint8_t WheelPos)
{
WheelPos = 255 - WheelPos;
if (WheelPos < 85)
{
return WS281x_Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170)
{
WheelPos -= 85;
return WS281x_Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return WS281x_Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
6、這里我簡單的寫了兩個演示程序
void Mode2_LED(uint8_t wait)
{
uint32_t timestamp = HAL_GetTick();
uint16_t i;
static uint8_t j;
static uint32_t next_time = 0;
uint32_t flag = 0;
if (next_time < wait)
{
if ((uint64_t)timestamp + wait - next_time > 0)
flag = 1;
}
else if (timestamp > next_time)
{
flag = 1;
}
if (flag)
{
j++;
next_time = timestamp + wait;
for (i = 0; i < LED_NUMS; i++)
{
WS281x_SetPixelColor(i, Wheel((i + j) & 255));
}
}
HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN);
}
void Mode1_LED(uint8_t wait)
{
uint32_t timestamp = HAL_GetTick();
uint16_t i;
static uint8_t j;
static uint32_t next_time = 0;
static uint8_t loop = 0;
if (loop == 0)
next_time = timestamp;
loop = 1; //首次調(diào)用初始化
if ((timestamp > next_time)) // && (timestamp - next_time < wait*5))
{
j++;
next_time = timestamp + wait;
for (i = 0; i < LED_NUMS; i++)
{
WS281x_SetPixelColor(i, Wheel(((i * 256 / (LED_NUMS)) + j) & 255));
}
}
HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,RESET_PULSE + WS2812_DATA_LEN);
}
7、在主函數(shù)中直接調(diào)用Mode1_LED和Mode2_LED函數(shù)即可。
OK 到這里就結(jié)束了,點亮之后相當炫酷。,大家可以借鑒 ,修改出自己獨特的風格。
審核編輯 :李倩
-
STM32
+關(guān)注
關(guān)注
2270文章
10915瀏覽量
356754 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5093瀏覽量
97802
原文標題:基于STM32G070RB的七彩星空燈教程
文章出處:【微信號:airX嵌入式,微信公眾號:airX嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論