久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: STM32F103C8T6單片機驅(qū)動WS2812,從零到放棄 [打印本頁]

作者: n04769431433    時間: 2024-10-27 23:25
標題: STM32F103C8T6單片機驅(qū)動WS2812,從零到放棄
首先是WS2812引腳初始化代碼,這點和其他配置GPIO代碼相同
void WS2812_PinInit(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
        WS2812_Reset();
}

其次是要向WS2812發(fā)送數(shù)據(jù),我們看一下WS2812時序要求


可以看到WS2812對時間要求比較嚴格,我們來操作GPIO
首先如果直接調(diào)用庫函數(shù)中的GPIO_SetBits()GPIO_ResetBits()函數(shù)
我們來試一下
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                GPIO_SetBits(GPIOB,GPIO_Pin_11);
                GPIO_ResetBits(GPIOB,GPIO_Pin_11);
        }
}



可以看到,單片機主頻72MHz才堪堪達到要求,如果更換其他型號主頻較低的單片機,可能就達不到要求了
我們打開GPIO_SetBits()GPIO_ResetBits()函數(shù)
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  GPIOx->BSRR = GPIO_Pin;
}
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  GPIOx->BRR = GPIO_Pin;
}


其中,assert_param()函數(shù)在這里的作用是檢查GPIO_SetBits庫函數(shù)傳入的參數(shù)是否為真,如果為真,就什么也不執(zhí)行,如果為假,就會在源程序編譯的時候報錯!
GPIOx->BSRR = GPIO_Pin;就是操作GPIO引腳設(shè)置高電平
   GPIOx->BRR = GPIO_Pin;  就是操作GPIO引腳設(shè)置低電平
那么,具體怎么操作呢
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                GPIOB->BSRR = GPIO_Pin_11;  //拉高PB11
                GPIOB->BRR   = GPIO_Pin_11;  //拉低PB11
        }
}



可以看到,高電平時間由原來的約160us變?yōu)榱爽F(xiàn)在的約40us
接下來就開始向WS2812發(fā)送 ‘0’ 碼
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
        }
}



可以看到,在添加12個nop函數(shù)后,高電平時序大概能滿足要求了
接下來就是滿足低電平的時間
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        }
}



低電平延時大概30個nop
接下來就是 ‘1’ 碼
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        }
}



因為要合并兩個函數(shù),所以預(yù)留了一點時間
接下來合并函數(shù)
void WS2812_SendBit(uint8_t Bit);
int main(void)
{
        WS2812_PinInit();
        while(1)
        {
                WS2812_SendBit(1);
                WS2812_SendBit(0);
        }
}
void WS2812_SendBit(uint8_t Bit)
{
        GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        if(Bit != 0)
                GPIOB->BRR = GPIO_Pin_11;//拉低PB11
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        GPIOB->BRR = GPIO_Pin_11;//拉低PB11
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}


可以看到,波形是可以滿足時序要求的
接下來就是向WS2812發(fā)送 3 字節(jié)的RGB數(shù)據(jù)
需要注意的是,WS2812數(shù)據(jù)發(fā)送順序是G R B,也就是綠色在前,然后是紅色,藍色。而不是紅色,綠色,藍色
void WS2812_SendRGB(uint8_t R,uint8_t G,uint8_t B);
int main(void)
{
        WS2812_PinInit();
        WS2812_SendRGB(50,0,0);
        while(1)
        {
        }
}

void WS2812_SendRGB(uint8_t R,uint8_t G,uint8_t B)
{
        for(int i = 0;i < 8;i ++)                                                                        //發(fā)送8位綠色數(shù)據(jù)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                if((G & (0x80 >> i)) == 0)
                        GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        }
        for(int i = 0;i < 8;i ++)                                                                        //發(fā)送8位紅色數(shù)據(jù)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                if((R & (0x80 >> i)) == 0)
                        GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        }
        for(int i = 0;i < 8;i ++)                                                                        //發(fā)送8位藍色數(shù)據(jù)
        {
                GPIOB->BSRR = GPIO_Pin_11;//拉高PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                if((B & (0x80 >> i)) == 0)
                        GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
                GPIOB->BRR  = GPIO_Pin_11;//拉低PB11
                __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
        }
}


可以看到,這顆燈珠已經(jīng)可以被點亮了







作者: devcang    時間: 2024-10-28 09:37
arduino卻容易很多
作者: n04769431433    時間: 2024-10-28 10:05
最后一段代碼WS2812_SendRGB以前要放10ms上電延時!!!要放10ms上電延時!!!10ms上電延時!!!




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 一区二区国产精品 | 夜夜操av| 在线观看网址你懂的 | 国产又爽又黄免费视频 | 国产乱码精品一区二区三 | 黄色一区二区三区 | 四虎在线观看视频 | 中文字幕一区二区三区在线观看 | 羞羞的视频网站 | 亚洲免费观看 | 日批视频免费在线观看 | 一区二区不卡 | 色av网| 国产欧美一区二区精品性色超碰 | 韩日在线视频 | 色吧综合 | 两性免费视频 | 天堂中文av| a视频在线观看 | 日本不卡在线播放 | 欧美黄色一区 | 欧美综合久久 | 97av在线视频 | 色六月婷婷 | 国产精品一区二区不卡 | 精品久久国产 | 黄色一级片免费 | 成人午夜小视频 | 午夜国产在线观看 | 男女久久久 | 夜夜骚av| 三级理论片 | 日本高清中文字幕 | 国产高清自拍视频 | 欧美日韩国产三级 | 欧美一级网站 | 日韩av手机在线 | 日韩中文视频 | 91国内视频| 国产成人+综合亚洲+天堂 | 日韩精品在线一区 |