欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 512|回復: 6
收起左側

求助:STC8G1K08A SPI模擬WS2812單總線,電平時間不符合預期

[復制鏈接]
ID:1155837 發表于 2026-2-23 16:56 | 顯示全部樓層 |閱讀模式
最近想試試用SPI模擬2812彩燈的單總線,理論上是可行的,因為SPI的特性是MOSI和MISO都是不歸零碼,只有需要改變的時候才改變,不會歸零。理論上是可行的。
于是我就根據STC的手冊寫了簡單的測試程序,手冊給的很清楚,寄存器也很少,很快便測試完成,但是電平時間不及預期。
這次使用的是24MHZ主頻的STC8G1K08A 8pin,SPI主頻選擇系統時鐘4分頻,也就是6MHZ,MOSI是P54。計算可得SPI在6mhz下傳輸1bit的時間是166.7ns,因此可以發送兩個數據來模擬邏輯1和邏輯0。(要注意STC的SPI MOSI在空閑時會輸出MISO讀到的電平,因此需要關閉MISO的數字輸入)
#define High_Code 0xf8//11111000
#define Zero_Code 0xC0//11000000

理論上來說邏輯0應該得到333ns高電平,1000ns高電平,但是實際測試并不是如此,高電平時間是正常的接近350ns,但是低電平時間長了接近一倍,有1700ns了
這是怎么回事呢?我用P33電平來檢測程序執行的時間,結果確實沒問題,1.5us左右,加上程序執行時間是合理的。但是不知道從哪多了幾百ns時間,總不能是主循環循環到這里要幾百ns吧?我手里沒有雙通道示波器,也就沒法測試兩個電平的相對關系了。
大家知道為什么嗎?現在這個代碼也不是不能用,2812彩燈只看高電平時間,低電平時間影響不大,但是如果之后做其他SPI控制,如果在傳輸期間也有這莫名其妙多出來的時間,會很影響使用的吧。
測試代碼如下:
void WS2812_Init(bit If_STC8G1K08A_8Pin,unsigned char Pin_Sel){//對于STC8G1K08A 8Pin需要執行不同的引腳初始化
    //初始化,并決定是否為主機從機
    P_SW1 &= 0XF3;//B3B2 = 0;
    SPSTAT = 0XC0;//清零中斷標志
    SPCTL = 0XD4;//SPEN = 1;SSIG = 1;先發高位;主機模式;時鐘空閑低電平;后時鐘沿采樣;SPI CLK為sysclk/4;
    if(If_STC8G1K08A_8Pin){
        WS2812_PinSet_8Pin(Pin_Sel);}
    else{
        WS2812_PinSet(Pin_Sel);}
}

void SPI_Send_1_Byte(unsigned char SPI_Data){
    P33 = 1;
    SPDAT = SPI_Data;//寫入后,硬件置SPIF = 0;
    while(!(SPSTAT & 0x80));//SPI控制器發送完數據后,退出while循環
    SPSTAT = 0xC0;//清空中斷標志
    P33 = 0;
}
void main(){
    P_SW2 |= 0x80;
    P3IE = 0x04;
    P3M0 |= 0x08; P3M1 &= ~0x08;
    WS2812_Init(1,54);//是8PIN單片機,引腳選擇P33
    while(1){
        if(P32){
        SPI_Send_1_Byte(Zero_Code);}
        else{
        SPI_Send_1_Byte(High_Code);
        }
    }
}


IMG_20260223_165223.jpg
IMG_20260223_165254.jpg
回復

使用道具 舉報

ID:1155837 發表于 2026-2-23 17:29 | 顯示全部樓層
好消息,我將Send_1_Byte函數直接展開到主循環進行測試
    while(1){
    P33 = 1;
    SPDAT = Zero_Code;//寫入后,硬件置SPIF = 0;
    while(!(SPSTAT & 0x80));//SPI控制器發送完數據后,退出while循環
    SPSTAT = 0xC0;//清空中斷標志
    P33 = 0;
    }
結果很明顯,現在觀察到低電平時間只有1400ns了。
理論上傳輸11 00 00 00,這一個字節的時間,低電平時間是1us,但是實際上卻是1.4us。
手冊說,寫SPDAT之后1bit時間之后,數據才會出現在SPI管腳上,也就是說這有166.7ns的延時。
結論是執行完P33 = 0,主循環回跳到P33 = 1這一行,中間隔了233.3ns?
測試了P33電平,結論確實如此。
大佬們,為什么主循環回跳需要這么長時間呢?
(圖片為P33波形)
IMG_20260223_172845.jpg
回復

使用道具 舉報

ID:1034262 發表于 2026-2-24 11:59 | 顯示全部樓層
你可以去STC官方論壇看看,他們有完整的程序,SPI驅動WS2812的,其實2812只要保證高電平時間在一定范圍就可以了,用于識別數據0或1,低電平只要不超過50us就不會復位,控制在30us之內為好。
回復

使用道具 舉報

ID:1155837 發表于 2026-2-24 16:43 | 顯示全部樓層
coody_sz 發表于 2026-2-24 11:59
你可以去STC官方論壇看看,他們有完整的程序,SPI驅動WS2812的,其實2812只要保證高電平時間在一定范圍就可 ...

我就是看了,不然都不知道MOSI空閑會輸出MISO電平。
但是實在是搞不懂為什么這51單片機,怎么在24mhz下,主循環回跳都要整整200ns
回復

使用道具 舉報

ID:688692 發表于 2026-2-26 22:17 | 顯示全部樓層
這樣的代碼不一樣在死等,直接軟件模擬效率還高得多。
STC8G@22.1184MHz
void nop(void)
{
}
void WS2812sendbyte(unsigned char byte)
{
        unsigned char i;
        i=8;
        EA=0;
                do
                {
                        WS2812IO=1;nop();
                        WS2812IO=byte&0x80;nop();
                        WS2812IO=0;nop();
                        byte=(byte<<1);                 //左移位
                }while(--i);
        EA=1;
}
回復

使用道具 舉報

ID:1155837 發表于 2026-2-26 23:47 | 顯示全部樓層
cnos 發表于 2026-2-26 22:17
這樣的代碼不一樣在死等,直接軟件模擬效率還高得多。

void nop(void)

ws2812這種軟件模擬確實更搞高效,傳輸一次也只需要幾十us,不過硬件spi不一定非得死等,可以用SPI中斷的。
回復

使用道具 舉報

ID:688692 發表于 2026-2-27 00:28 | 顯示全部樓層
SPI中斷,判斷數據要發送的bit是0還是1,移位數據,選一個對應時序的char扔進寄存器,觸發SPI發送,然后等中斷。或者趁中斷沒來之前先去干點別的事情,等1uS后,中斷來了,重復這些事情……
必要性實在是不是很強
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表