【Ai-M61-32SU入门】利用可编程IO简单驱动WS2812

[复制链接]
查看653 | 回复13 | 2024-6-6 20:14:42 | 显示全部楼层 |阅读模式
WS2812内置IC通过一根数据线即可控制多个灯珠的RGB颜色变化,时序如下图

微信截图_20240606191602.png

微信截图_20240606191513.png

通常驱动都是手动控制IO电平和延时,或者借助SPI外设,但是在Ai-M61-32S所用的BL616上有一种更简单的驱动方法
这个芯片的GPIO有一种可编程输出模式,看用户文档的描述很适合用来驱动WS2812
微信截图_20240603223756.png

可惜官方没提供这个模式的例程,论坛和网上也没搜到,不过在我的尝试下成功驱动了WS2812
Ai-M61-32S默认的时钟是40M,一个时钟周期是0.025us,ws2812的0码高电平0.3us低电平0.6us,1码高电平0.6us低电平0.3us

cr_code0_high_time=0.3/0.025=12

cr_code1_high_time=0.6/0.025=24
cr_code_total_time=36
设置高电平先发送,空闲低电平,GPIO初始化代码如下

  1. #define WS2812PIN GLB_GPIO_PIN_0
  2. void ws2812_gpio_init(void)
  3. {
  4.     GLB_GPIO_Cfg_Type gpio_cfg;
  5.     GLB_GPIO_FIFO_CFG_Type gpio_fifo_cfg;

  6.     gpio_cfg.drive = 0;
  7.     gpio_cfg.smtCtrl = 0;
  8.     gpio_cfg.outputMode = GPIO_DMA_OUTPUT_VALUE_MODE;
  9.     gpio_cfg.gpioMode = GPIO_MODE_OUTPUT;
  10.     gpio_cfg.pullType = GPIO_PULL_NONE;
  11.     gpio_cfg.gpioPin = WS2812PIN;
  12.     gpio_cfg.gpioFun = GPIO_FUN_GPIO;
  13.     GLB_GPIO_Init(&gpio_cfg);

  14.     gpio_fifo_cfg.code0FirstTime = 12;
  15.     gpio_fifo_cfg.code1FirstTime = 24;
  16.     gpio_fifo_cfg.codeTotalTime = 36;
  17.     gpio_fifo_cfg.code0Phase = GPIO_FIFO_PHASE_FIRST_HIGH;
  18.     gpio_fifo_cfg.code1Phase = GPIO_FIFO_PHASE_FIRST_HIGH;
  19.     gpio_fifo_cfg.idle = GPIO_FIFO_IDLE_LOW;
  20.     gpio_fifo_cfg.latch = GPIO_FIFO_LATCH_WRITE;
  21.     GLB_GPIO_Fifo_Init(&gpio_fifo_cfg);
  22. }
复制代码
BL616提供了128x16bits的缓冲区向GPIO写入数据,每16个GPIO为1组,例如IO0~IO15为1组IO16~IO31为1组,IO0和IO16都对应第0位,对应bit是1发送逻辑1码否则发送逻辑0码,写入缓冲区后开启发送并等待发送完成,实现发送代码如下
  1. void ws2812_write_byte(uint8_t byte)
  2. {
  3.     uint16_t bits[8];
  4.     uint8_t i = 0;
  5.     while (i < 8)
  6.     {
  7.         if(byte&0x80)
  8.             bits[i] = 1<<(WS2812PIN%16);
  9.         else
  10.             bits[i] = 0;
  11.         byte <<= 1;
  12.         i += 1;
  13.     }
  14.     GLB_GPIO_Fifo_Clear();
  15.     GLB_GPIO_Fifo_Push(bits,8);
  16.     GLB_GPIO_Fifo_Enable();
  17.     while (GLB_GPIO_Fifo_GetCount()!=128);
  18. }

  19. void ws2812_reset()
  20. {
  21.     bflb_mtimer_delay_us(80);
  22. }

  23. void ws2812_write_rgb(uint8_t r,uint8_t g,uint8_t b)
  24. {
  25.     ws2812_write_byte(g);
  26.     ws2812_write_byte(r);
  27.     ws2812_write_byte(b);
  28. }
复制代码
测试代码
  1. int main(void)
  2. {
  3.     board_init();
  4.     gpio = bflb_device_get_by_name("gpio");
  5.     bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_OUTPUT | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_0);
  6.   
  7.     ws2812_gpio_init();
  8.     ws2812_write_rgb(25,0,0);
  9.     ws2812_write_rgb(0,25,0);
  10.     ws2812_write_rgb(0,0,25);
  11.     ws2812_write_rgb(25,0,25);
  12.     ws2812_reset();
  13.     while (1) {
  14.         bflb_gpio_set(gpio, GPIO_PIN_12);
  15.         bflb_mtimer_delay_ms(1000);
  16.         bflb_gpio_reset(gpio, GPIO_PIN_12);
  17.         bflb_mtimer_delay_ms(1000);
  18.     }
  19. }
复制代码
运行效果
微信截图_20240606192640.png



回复

使用道具 举报

lazy | 2024-6-6 23:29:08 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-6-7 08:28:25 | 显示全部楼层
开起来很不错
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

WT_0213 | 2024-6-7 08:30:48 | 显示全部楼层
回复

使用道具 举报

1084504793 | 2024-6-7 08:37:38 | 显示全部楼层
回复

使用道具 举报

爱笑 | 2024-6-7 08:41:12 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

wxlinus | 2024-6-7 09:00:54 | 显示全部楼层
来点学习学习
回复 支持 反对

使用道具 举报

lovzx | 2024-6-7 09:43:34 | 显示全部楼层
学习
回复

使用道具 举报

iiv | 2024-6-8 18:12:48 | 显示全部楼层
很棒
回复

使用道具 举报

jkernet | 2024-6-8 21:57:53 | 显示全部楼层
点赞
回复

使用道具 举报

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

本版积分规则