Keil+ARM内核下C+汇编混合编程驱动WS2812

使用某些主频比较低的芯片时比如航顺的HK32F030M系列的芯片时,该芯片的主频使用最高32M的内部RC振荡器,没有PLL,没有DMA,对于WS2812这类对时钟频率要求比较高的IC有些困难。虽然使用一些技巧也是可以驱动的,比如直接使用寄存器操作,减少不必要的开销等。

为了将驱动负担降低到底,我尝试使用汇编的方式驱动WS2812,并且取得成功,在MCU工作在32M的状况下,成功将刷新时钟上到800k。

下面介绍一下具体方法。在正常工程中,添加一个新文件(Add New Item),文件类型选择asm (*.s)

;//驱动WS2812的引脚 ,高速翻转达到200ns,
;/*传入参数:
;1.引脚的地址
;2.一个灯的32位数据
;*/
;LED0 EQU  0x48000C18 PD4
    
    AREA DriveWS2812,CODE ,READONLY    
    EXPORT F_DriveWS2812;导出函数
F_DriveWS2812
    PUSH {R0,R1,R2,R3,R4,R5,R6,R7, LR};R2,,R3,R4,R5,R6,R7
    MOVS R7,R1;LSL#8;将参数2的值先向左移8位到数据的24bit高位位置
    MOVS R4,#0x01
    LSLS R4,R4,#23;0x800000
    MOVS R3,#0;R3用于24位计数
    MOVS R5,R0;
    ADDS R5,#0x10;BSx地址改变到BRx地址, 用于复位
    MOVS R6,#0x10;操作寄存器用的值输出Gpio_Pin_4
LOOP
    ADDS R3,R3,#1
    CMP R3,#24
    BHI LOOP_END
    ANDS R7,R7,R4;和0x800000做与后比较

    CMP R7,#0
    BLS DAT0;大于
    STR R6,[R0];输出1
    LSLS R1,R1,#1
    MOVS R7,R1    
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    STR R6,[R5] ;输出0
    B LOOP
DAT0
    STR R6,[R0];输出1    
    LSLS R1,R1,#1
    MOVS R7,R1
    STR R6,[R5] ;输出0
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    B LOOP
LOOP_END
    POP {R0,R1,R2,R3,R4,R5,R6,R7,PC};,R2,R3,R4,R5,R6,R7

    
    END

调用方法

{
uint32_t j;
GPIO_INIT();

j=0;
for(i=0;i<32;i++){//驱动灯珠的数量32
    F_DriveWS2812(LEDPIN,j);//汇编函数调用
}
    j++;//颜色

Delay(500);//帧间隔

}

你可能感兴趣的:(汇编,c语言,单片机)