今天在调RGB灯带时发现:颜色,数量,都能正常显示
但是就是每隔一会,某颗RGB灯都会闪一下,
正常:

异常:(某个灯闪烁)

最后发现是,是因为中断的影响
因为51单片机没有中断优先级的概念,所以任何意外中断都会打断时序。即使是中断内没有任何代码,进入的过程也会花费几us,导致时序错乱
逻辑分析仪也会抓到了这一点

解决方法:
操作时关闭总中断
c
GIE = 0; // 关闭总中断
send_px(10,0,1); // 操控灯
GIE = 1; // 开启总中断
使用方法
TM1804的时序规则(芯片参考手册)

相当于0是短一点的高电平加一段低电平
1是长一点的高电平加一段低电平
发完全部灯后,要间隔200us以上让灯的配置导入
代码
TM1804在8位单片机上的代码(TXD修改成自己的引脚)
当前适配的MCU是16Mhz 2T,单个指令操作是125ns,请修改nop数量来匹配时序
用法示例:
c
#include "RGB_tm1084.h" //导入RGB灯头文件
void main()
{
while(1)
{
delay_ms(200); //间隔200ms切换颜色
GIE = 0; //关闭总中断
send_px_num(3,10,0,1); //点亮3个灯,RGB值10 0 1,满载255
GIE = 1; //开启总中断
}
}
RGB_tm1084.h
c
/*
* TM1804 RGB灯幻彩变化
*/
#ifndef TM1804_H
#define TM1804_H
#include <sc.h> // 单片机头文件
// 自定义参数
#define TXD RA0 //LED控制端口
#define IC 54 //LED灯总个数
// 操作一个灯
void send_px_one(unsigned char R,unsigned char G,unsigned char B);
// 操作指定个数灯
void send_px_num(unsigned int num,unsigned char R,unsigned char G,unsigned char B);
// 操作所有灯
void send_px_all(unsigned char R,unsigned char G,unsigned char B);
//待加入:
// 呼吸灯
// 彩虹渐变
// 流光效果
// 等等
#endif
RGB_tm1084.c
c
/*********************
* TM1804 RGB灯幻彩变化。
********************/
#include "RGB_tm1084.h"
#define nop asm("nop") // 一个nop大概0.125us(16MHz 2T)
unsigned int LED_PX; //像素点数
unsigned char PWM; //TM1804灰度数据
unsigned char Rda,Gda,Bda; //R、G、B灰度数据
unsigned char LED_data; //可位操作的数据发送暂存变量声明
#define bit0 ((LED_data) & 0x01)
#define bit1 ((LED_data) & 0x02)
#define bit2 ((LED_data) & 0x04)
#define bit3 ((LED_data) & 0x08)
#define bit4 ((LED_data) & 0x10)
#define bit5 ((LED_data) & 0x20)
#define bit6 ((LED_data) & 0x40)
#define bit7 ((LED_data) & 0x80)
/**********************************延时函数*************************************/
void send_px_reset() // 总间隔延时 200us以上
{
unsigned int j;
for(j=550;j>0;j--);
}
// 注意进入信号操作时,要关闭总中断,不然会打乱时序
/********************发送0码函数,高电平400ns,周期1.25us************************/
inline void send_data_0()
{
TXD=1; // 高电平 300ns
nop; // 一个nop大概0.125us(16MHz 2T) 300ns
TXD=0; // 低电平 900ns
nop;nop;nop;
//实测:
//高电平 1个nop 375ns,引脚操作耗费250ns,nop耗费125ns
//低电平 3个nop 1125ns
//外面if耗费 625ns
//切换RGB值耗费 750ns
}
/*******************发送1码函数,高电平800ns,周期1.25us*************************/
inline void send_data_1()
{
TXD=1; // 高电平 900ns
nop;nop;nop;nop;nop;
TXD=0; // 低电平 300ns
// 实测:
// 高电平 5个nop 875ns
// 低电平 0个nop 625ns
}
/*************发送1个字节数据,8位颜色*******/
inline void send_data(unsigned char LED_data)
{
if(bit7) send_data_1(); else send_data_0();
if(bit6) send_data_1(); else send_data_0();
if(bit5) send_data_1(); else send_data_0();
if(bit4) send_data_1(); else send_data_0();
if(bit3) send_data_1(); else send_data_0();
if(bit2) send_data_1(); else send_data_0();
if(bit1) send_data_1(); else send_data_0();
if(bit0) send_data_1(); else send_data_0();
}
/*********发送1帧数据************/
// 操作一个灯 原来颜色顺序是GRB
void send_px_one(unsigned char R,unsigned char G,unsigned char B)
{
send_data(G); //发送R灰度数据
send_data(R); //发送G灰度数据
send_data(B); //发送B灰度数据
}
// 操作指定数量的灯
void send_px_num(unsigned int num,unsigned char R,unsigned char G,unsigned char B) //操作指定个数灯
{
unsigned int i;
for(i=0;i<num;i++)
{
send_data(G); //发送R灰度数据
send_data(R); //发送G灰度数据
send_data(B); //发送B灰度数据
}
}
// 操作所有灯
void send_px_all(unsigned char R,unsigned char G,unsigned char B)
{
unsigned int i;
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); //复位延时
// }
// }
// }
//}
/*================================结束==========================================*/