最近想試試用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);
}
}
}
|