今天在调RGB灯带时发现:颜色,数量,都能正常显示
但是就是每隔一会,某颗RGB灯都会闪一下,
正常:
异常:(某个灯闪烁)
最后发现是,是因为中断的影响
因为51单片机没有中断优先级的概念,所以任何意外中断都会打断时序。即使是中断内没有任何代码,进入的过程也会花费几us,导致时序错乱
逻辑分析仪也会抓到了这一点
解决方法:
操作时关闭总中断
GIE=0;// 关闭总中断send_px(10,0,1);// 操控灯GIE=1;// 开启总中断代码:
TM1804的时序规则(芯片参考手册)
TM1804在8位单片机上的代码(TXD修改成自己的引脚)
当前适配的MCU是16Mhz 2T,单个指令操作是125ns,请修改nop数量来匹配时序
main用法示例:
#include"tm1804.h"//导入RGB灯头文件voidmain(){while(1){delay_ms(200);//间隔200ms切换颜色GIE=0;//关闭总中断send_px_num(3,10,0,1);//点亮3个灯,RGB值10 0 1,满载255GIE=1;//开启总中断}}TM1804.h
/* * TM1804 RGB灯幻彩变化 */#ifndefTM1804_H#defineTM1804_H#include<sc.h>// 单片机头文件// 自定义参数#defineTXDRA0//LED控制端口#defineIC54//LED灯总个数// 操作一个灯voidsend_px_one(unsignedcharR,unsignedcharG,unsignedcharB);// 操作指定个数灯voidsend_px_num(unsignedintnum,unsignedcharR,unsignedcharG,unsignedcharB);// 操作所有灯voidsend_px_all(unsignedcharR,unsignedcharG,unsignedcharB);//待加入:// 呼吸灯// 彩虹渐变// 流光效果// 等等#endifTM1084.c
/********************* * TM1804 RGB灯幻彩变化。 ********************/#include"tm1804.h"#definenopasm("nop")// 一个nop大概0.125us(16MHz 2T)unsignedintLED_PX;//像素点数unsignedcharPWM;//TM1804灰度数据unsignedcharRda,Gda,Bda;//R、G、B灰度数据unsignedcharLED_data;//可位操作的数据发送暂存变量声明#definebit0((LED_data)&0x01)#definebit1((LED_data)&0x02)#definebit2((LED_data)&0x04)#definebit3((LED_data)&0x08)#definebit4((LED_data)&0x10)#definebit5((LED_data)&0x20)#definebit6((LED_data)&0x40)#definebit7((LED_data)&0x80)/**********************************延时函数*************************************/voidsend_px_reset()// 总间隔延时 200us以上{unsignedintj;for(j=550;j>0;j--);}// 注意进入信号操作时,要关闭总中断,不然会打乱时序/********************发送0码函数,高电平400ns,周期1.25us************************/inlinevoidsend_data_0(){TXD=1;// 高电平 300nsnop;// 一个nop大概0.125us(16MHz 2T) 300nsTXD=0;// 低电平 900nsnop;nop;nop;//实测://高电平 1个nop 375ns,引脚操作耗费250ns,nop耗费125ns//低电平 3个nop 1125ns//外面if耗费 625ns//切换RGB值耗费 750ns}/*******************发送1码函数,高电平800ns,周期1.25us*************************/inlinevoidsend_data_1(){TXD=1;// 高电平 900nsnop;nop;nop;nop;nop;TXD=0;// 低电平 300ns// 实测:// 高电平 5个nop 875ns// 低电平 0个nop 625ns}/*************发送1个字节数据,8位颜色*******/inlinevoidsend_data(unsignedcharLED_data){if(bit7)send_data_1();elsesend_data_0();if(bit6)send_data_1();elsesend_data_0();if(bit5)send_data_1();elsesend_data_0();if(bit4)send_data_1();elsesend_data_0();if(bit3)send_data_1();elsesend_data_0();if(bit2)send_data_1();elsesend_data_0();if(bit1)send_data_1();elsesend_data_0();if(bit0)send_data_1();elsesend_data_0();}/*********发送1帧数据************/// 操作一个灯 原来颜色顺序是GRBvoidsend_px_one(unsignedcharR,unsignedcharG,unsignedcharB){send_data(G);//发送R灰度数据send_data(R);//发送G灰度数据send_data(B);//发送B灰度数据}// 操作指定数量的灯voidsend_px_num(unsignedintnum,unsignedcharR,unsignedcharG,unsignedcharB)//操作指定个数灯{unsignedinti;for(i=0;i<num;i++){send_data(G);//发送R灰度数据send_data(R);//发送G灰度数据send_data(B);//发送B灰度数据}}// 操作所有灯voidsend_px_all(unsignedcharR,unsignedcharG,unsignedcharB){unsignedinti;for(i=0;i<LED_PX;i++){send_data(G);//发送R灰度数据send_data(R);//发送G灰度数据send_data(B);//发送B灰度数据}}/*===============================主函数=======================================*///void main()//{// unsigned char i;// LED_PX=IC; //像素点数等于TM1804个数// Rda=Gda=Bda=0; //R、G、B灰度数据复位清零// while(1)// {// for(i=0;i<PWM;i++) //红色渐亮// {// Rda=i; //灰度计算// send_px(); //发送灰度数据// delay(10); //复位延时// }// flag=1; //标志位置位// while(flag) //标志位置位后循环函数// {// for(i=0;i<PWM;i++) //红色渐灭,绿色渐亮// {// Gda=i;// Rda=PWM-i; //灰度计算// send_px(); //发送灰度数据// delay(10); //复位延时// }// for(i=0;i<PWM;i++) //绿色渐灭,蓝色渐亮// {// Bda=i;// Gda=PWM-i; //灰度计算// send_px(); //发送灰度数据// delay(10); //复位延时// }// for(i=0;i<PWM;i++) //蓝色渐灭,红色渐亮// {// Rda=i;// Bda=PWM-i; //灰度计算// send_px(); //发送灰度数据// delay(10); //复位延时// }// }// }//}/*================================结束==========================================*/