杰理-701-单线灯-ws2812-驱动
LED_gradual_open(); //调用后 呼吸灯
set_led_colour(R,G,B);//具体颜色
spi_dma_set_addr_for_isr //spi 配置dma 后灯才亮
#define LED_H 0x7c
#define LED_L 0x40
发送高位和地位的字节,具体使用逻辑分析仪配合灯的时序调试
spi 时钟修改
开机初始化spi
makefile添加led_spi.c
IO口高低电平输出,若没有led电源没有控制,则忽略
void user_set_gpio(u32 gpio, bool level)
{
gpio_set_pull_down(gpio, 0);
gpio_set_pull_up(gpio, 0);
gpio_set_die(gpio, 1);
gpio_set_hd(gpio, 0);//看需求是否需要开启强推,会导致芯片功耗大
gpio_set_hd0(gpio, 0);
gpio_set_direction(gpio, 0);
gpio_set_output_value(gpio, level); //1高0低
}
#include "system/includes.h"
#include "app_config.h"
#include "asm/spi.h"
#if G_log_total
#if 1
#define G_log(format, ...) printf("->>>--- GZH ---<<<-" format "\r\n", ## __VA_ARGS__)
#else
#define G_log(...)
#endif
#else
#define G_log(...)
#endif
#if SINGLE_LED
static const u8 SPI1_DO[2] = {
IO_PORTB_01,//'A'
IO_PORTC_05 //'B'
};
static const u8 SPI2_DO[2] = {
IO_PORTB_10,//'A'
IO_PORT_DM //'B'
};
#define LED_SPI JL_SPI2
#define LED_SPI_PORT 'A'
#define LED_SPI_DAT_BAUD 8000000
#define LED_SPI_REST_BAUD 1000000
#define LED_SPI_CLOCK_BASE clk_get("lsb")
static OS_SEM led_spi_sem;
static u32 spi_do = 0;
static u8 led_spi_busy = 0;
static u8 led_spi_sus = 0;
void user_led_spi_test(void);
___interrupt
void led_spi_isr()
{
LED_SPI->CON &= ~BIT(13); //关闭中断
LED_SPI->CON |= BIT(14); //清pnding
os_sem_post(&led_spi_sem);
led_spi_busy = 0;
}
void led_spi_init(void)
{
if ((u32)LED_SPI == (u32)JL_SPI1) {
// spi_do = SPI1_DO[LED_SPI_PORT - 'A'];
SFR(JL_IOMAP->OCH_CON1, 4, 1, LED_SPI_PORT - 'A');
request_irq(IRQ_SPI1_IDX, 0, led_spi_isr, 0);
} else {
// spi_do = SPI2_DO[LED_SPI_PORT - 'A'];
SFR(JL_IOMAP->OCH_CON1, 5, 1, LED_SPI_PORT - 'A');
request_irq(IRQ_SPI2_IDX, 0, led_spi_isr, 0);
}
gpio_set_die(TCFG_HW_SPI2_PORT_DO, 1);
gpio_set_direction(TCFG_HW_SPI2_PORT_DO, 0);
gpio_set_pull_up(TCFG_HW_SPI2_PORT_DO, 0);
gpio_set_pull_down(TCFG_HW_SPI2_PORT_DO, 0);
gpio_write(TCFG_HW_SPI2_PORT_DO, 0);
os_sem_create(&led_spi_sem, 1);
LED_SPI->CON = 0x4021;
}
void led_spi_rgb_to_24byte(u8 r, u8 g, u8 b, u8 *buf, int idx)
{
buf = buf + idx * 24;
u32 dat = ((g << 16) | (r << 8) | b);
for (u8 i = 0; i < 24; i ++) {
if (dat & BIT(23 - i)) {
*(buf + i) = 0x7c;
} else {
*(buf + i) = 0x60;
}
}
}
void led_spi_rest()
{
u8 tmp_buf[16] = {0};
LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_REST_BAUD - 1;
LED_SPI->CON |= BIT(14);
LED_SPI->ADR = (u32)tmp_buf;
LED_SPI->CNT = 16;
while (!(LED_SPI->CON & BIT(15)));
LED_SPI->CON |= BIT(14);
}
void led_spi_send_rgbbuf(u8 *rgb_buf, u16 led_num) //rgb_buf的大小 至少要等于 led_num * 24
{
if (!led_num) {
return;
}
while (led_spi_sus) {
os_time_dly(1);
}
led_spi_busy = 1;
// led_spi_rest();
LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_DAT_BAUD - 1;
LED_SPI->CON |= BIT(14);
LED_SPI->ADR = (u32)rgb_buf;
LED_SPI->CNT = led_num * 24;
while (!(LED_SPI->CON & BIT(15)));
LED_SPI->CON |= BIT(14);
led_spi_busy = 0;
}
void led_spi_send_rgbbuf_isr(u8 *rgb_buf, u16 led_num) //rgb_buf的大小 至少要等于 led_num * 24
{
if (!led_num) {
return;
}
while (led_spi_sus) {
os_time_dly(1);
}
led_spi_busy = 1;
os_sem_pend(&led_spi_sem, 0);
led_spi_rest();
LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_DAT_BAUD - 1;
LED_SPI->CON |= BIT(14);
LED_SPI->ADR = (u32)rgb_buf;
LED_SPI->CNT = led_num * 24;
LED_SPI->CON |= BIT(13);//打开中断
}
u8 led_spi_suspend(void)
{
if (led_spi_sus) {
return 1;
}
if (led_spi_busy) {
return 1;
}
LED_SPI->CON |= BIT(14);
LED_SPI->CON &= ~BIT(0);
led_spi_sus = 1;
return 0;
}
u8 led_spi_resume(void)
{
if (!led_spi_sus) {
return 0;
}
gpio_set_die(TCFG_HW_SPI2_PORT_DO, 1);
gpio_set_direction(TCFG_HW_SPI2_PORT_DO, 0);
gpio_set_pull_up(TCFG_HW_SPI2_PORT_DO, 0);
gpio_set_pull_down(TCFG_HW_SPI2_PORT_DO, 0);
gpio_write(TCFG_HW_SPI2_PORT_DO, 0);
LED_SPI->CON = 0x4021;
led_spi_sus = 0;
return 0;
}
// static u8 spi_dat_buf[24 * 20] __attribute__((aligned(4)));
#define LED_NUM 12
#define LED_H 0x7c
#define LED_L 0x40
u8 spi_dat_buf[24*LED_NUM] = {0};
//设置全部灯的颜色
void set_led_colour(u8 red, u8 green, u8 blue)
{
printf(" red = %d green = %d blue = %d ",red,green,blue);
#if 1
for(u8 i=0;i<LED_NUM;i++){
for(u8 j=0;j<8;j++){
spi_dat_buf[(i*24)+j] = (green & BIT(7-j)) ? LED_H : LED_L;
}
for(u8 j=0;j<8;j++){
spi_dat_buf[(i*24)+j+8] = (red & BIT(7-j)) ? LED_H : LED_L;
}
for(u8 j=0;j<8;j++){
spi_dat_buf[(i*24)+j+16] = (blue & BIT(7-j)) ? LED_H : LED_L;
}
}
#endif
// put_buf(spi_dat_buf,sizeof(spi_dat_buf));
}
extern void wdt_clear();
void user_led_spi_test(void)
{
printf("****************** led spi test *******************\n");
u8 spi_pro=SPI2;
spi_open(spi_pro);
u8 cnt = 0;
u8 pulse = 0;
// local_irq_disable();
// memset(spi_dat_buf,LED_L,sizeof(spi_dat_buf));
// while (1)
{
// cnt ++;
// led_spi_rgb_to_24byte(cnt, 255 - cnt, 0, spi_dat_buf, 0);
// led_spi_rgb_to_24byte(0, 0, cnt, spi_dat_buf, 1);
#if 0
spi_dma_send(spi_pro,spi_dat_buf, sizeof(spi_dat_buf)); //等待的方式,建议用在发的数据量小的场合
#else
spi_dma_set_addr_for_isr(spi_pro,spi_dat_buf, 24*LED_NUM,0); //中断的方式,建议用在发的数据量大的场合
#endif
printf(" ----- ");
os_time_dly(50);
wdt_clear();
}
}
void led_spi_test(void)
{
user_led_spi_test();
printf("****************** led spi test *******************\n");
led_spi_init();
u8 cnt = 0;
u8 pulse = 0;
// local_irq_disable();
while (1) {
// cnt ++;
// led_spi_rgb_to_24byte(cnt, 255 - cnt, 0, spi_dat_buf, 0);
// led_spi_rgb_to_24byte(0, 0, cnt, spi_dat_buf, 1);
#if 0
led_spi_send_rgbbuf(spi_dat_buf, sizeof(spi_dat_buf)); //等待的方式,建议用在发的数据量小的场合
#else
led_spi_send_rgbbuf_isr(spi_dat_buf, sizeof(spi_dat_buf)); //中断的方式,建议用在发的数据量大的场合
#endif
printf(" +++++ ");
os_time_dly(50);
wdt_clear();
}
}
#define HIGT_BRIGHT 150
#define LOW_BRIGHT 0
#define HIGT_STEP 10
static u16 gradual_timer = 0;
static int colour[3] = {0};
static u8 type = 0;
void gradual_timer_func(void)
{
// G_log(" 0 type = %d R = %d G = %d B = %d ",type,colour[0],colour[2],colour[2]);
user_set_gpio(IO_PORTB_06,0);
switch(type){
case 0:
colour[0] += HIGT_STEP;
colour[1] = 0;
colour[2] = 0;
if(colour[0] >= HIGT_BRIGHT ){
type = 1;
colour[0] = HIGT_BRIGHT;
}
break;
case 1:
colour[0] -= HIGT_STEP;
colour[1] = 0;
colour[2] = 0;
if(colour[0] <= LOW_BRIGHT ){
type = 2;
}
break;
case 2:
colour[0] = 0;
colour[1] += HIGT_STEP;
colour[2] = 0;
if(colour[1] >= HIGT_BRIGHT ){
type = 3;
colour[1] = HIGT_BRIGHT;
}
break;
case 3:
colour[0] = 0;
colour[1] -= HIGT_STEP;
colour[2] = 0;
if(colour[1] <= LOW_BRIGHT ){
type = 4;
}
break;
case 4:
colour[0] = 0;
colour[1] = 0;
colour[2] += HIGT_STEP;
if(colour[2] >= HIGT_BRIGHT ){
colour[2] = HIGT_BRIGHT;
type = 5;
}
break;
case 5:
colour[0] = 0;
colour[1] = 0;
colour[2] -= HIGT_STEP;
if(colour[2] <= LOW_BRIGHT ){
type = 0;
}
break;
}
// G_log(" 1 type = %d R = %d G = %d B = %d ",type,colour[0],colour[2],colour[2]);
set_led_colour(colour[0],colour[1],colour[2]);
// user_led_spi_test();
spi_dma_set_addr_for_isr(SPI2,spi_dat_buf, 24*LED_NUM,0);
}
void LED_gradual_close(void)
{
user_set_gpio(IO_PORTB_06,1);
if(gradual_timer){
sys_timer_del(gradual_timer);
gradual_timer = 0;
}
set_led_colour(0,0,0);
spi_dma_set_addr_for_isr(SPI2,spi_dat_buf, 24*LED_NUM,0);
memset(colour,0,sizeof(colour));
type = 0;
}
void LED_gradual_open(void)
{
LED_gradual_close();
if(!gradual_timer){
gradual_timer = sys_timer_add(NULL,gradual_timer_func,50);
}
}
#endif