51单片机TM1804控制RGB灯闪烁的问题及例程

今天在调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);  //复位延时
//			}
//		}
//	}
//}
/*================================结束==========================================*/
相关推荐
QYR-分析5 分钟前
汽车碳刷市场深度解析:存量维保支撑需求,电动化重塑行业格局
单片机·嵌入式硬件·汽车
沐欣工作室_lvyiyi20 分钟前
基于单片机的升降式立体车库系统设计(论文+源码)
单片机·嵌入式硬件·毕业设计·rfid·单片机毕业设计·数据库设计·物联网毕业设计
碧海银沙音频科技研究院1 小时前
基于炬芯ATS3089X的BLE opus音频传输系统设计
stm32·单片机·嵌入式硬件
Yiran_G2 小时前
智能家居自动化为什么会失效?从一次开灯失败看无线通信链路
嵌入式硬件·物联网·智能家居
编程圈子2 小时前
I.MX6U 裸机开发 25. PWM 与 LCD 背光
单片机·嵌入式硬件
创界工坊工作室3 小时前
35-基于AT89C51单片机的罐头生产线传送系统设计
stm32·单片机·嵌入式硬件·51单片机·proteus·生产线
qq_401700413 小时前
MCU串口接收不定长数据的三种方案,哪种最稳?
stm32·单片机·嵌入式硬件
inrichtt4 小时前
第七课时:STM32时钟系统揭秘:从零理解时钟树
c语言·数据结构·stm32·单片机·嵌入式硬件
硅基手札4 小时前
【Linux 内核专栏 17】进程间通信 IPC(上)— 管道·信号·System V IPC·mmap·文件锁
linux·运维·服务器·stm32·单片机·mcu
国科安芯5 小时前
无方向脚如何既快又稳:ASC0101S 自动方向感应机理与边沿加速应用研究
网络·嵌入式硬件·低轨卫星·商业航天·抗辐射