⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmx512.c

📁 基于DMX512协议在AT89S51单片机上的收发程序
💻 C
字号:
#include <reg51.h>
#define uchar unsigned char
#define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/
#define TRUE 1	   //IIC返回应答正确
#define FALSE 0
sbit T_D=P3^1;	  //TXD
sbit R_D=P3^2;	  //RXD
sbit led_green=P2^0;    //信号发送指示灯
sbit led_yellow=P2^1;  //信号接收指示灯
sbit TorR = P3^7;		//485接收标志
sbit SDA=P0^1;/*假设由P0.1和P0.2控制*/
sbit SCL=P0^2;
bit flag;	 //数据标志位

static uchar rdata[72];	 //接收数据缓冲区
static uchar n=72;
static uchar counter;	 //接收计数器
static uchar totalnum;
static uchar times;		 //分三次接收标记位

void ldelay(uchar t)
{
	uchar i;
	uchar k=200;
	while(t-->0)
	{
		while(k-->0)
			for(i=0;i<255;i++);
	}
}
/********** Function Definition函数定义 ************/

    void DELAY(uchar t) /*延时函数*/
    {
        while(t!=0)
            t--;
    }

    void I2C_Start(void)
    {
        /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
        SDA=1;
        SCL=1;
        DELAY(DELAY_TIME);
        SDA=0;
        DELAY(DELAY_TIME);
        SCL=0;
        DELAY(DELAY_TIME);
    }

    void I2C_Stop(void)
    {
        /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
        SDA=0;
        SCL=1;
        DELAY(DELAY_TIME);
        SDA=1;
        DELAY(DELAY_TIME);
        SCL=0;
        DELAY(DELAY_TIME);
    }

    void SEND_0(void)   /* SEND ACK */
    {
  		/*发送0,在SCL为高电平时使SDA信号为低*/
        SDA=0;
        SCL=1;
        DELAY(DELAY_TIME);
        SCL=0;
        DELAY(DELAY_TIME);
    }

    void SEND_1(void)
    {
        /*发送1,在SCL为高电平时使SDA信号为高*/
        SDA=1;
        SCL=1;
        DELAY(DELAY_TIME);
        SCL=0;
        DELAY(DELAY_TIME);
    }

    bit Check_Acknowledge(void)
    {
        /*发送完一个字节后检验设备的应答信号*/
        SDA=1;
        SCL=1;
        DELAY(DELAY_TIME/2);
        F0=SDA;
        DELAY(DELAY_TIME/2);
        SCL=0;
        DELAY(DELAY_TIME);
        if(F0==1)
		{
            return FALSE;
		}
        return TRUE;
    }

    void WriteI2CByte(char b)
    {
        /*向I2C总线写一个字节*/
        uchar i;
        for(i=0;i<8;i++)
		{
            if((b<<i)&0x80)
                SEND_1();
 			else
                SEND_0();
		}
    }

 

    uchar ReadI2CByte(void)
    {
        /*从I2C总线读一个字节*/
        uchar b=0,i;
        for(i=0;i<8;i++)
        {
            SDA=1;    /*释放总线*/
            SCL=1;    /*接受数据*/
            DELAY(10);
            F0=SDA;
            DELAY(10);
            SCL=0;
            if(F0==1)
            {
                b=b<<1;
                b=b+0x01;
            }
            else
                b=b<<1;
        }
        return b;
    }


/**********以下为读写24c02的函数**********/
/*void Write_One_Byte(char addr,char thedata)
{
	bit acktemp=1;
	
	I2C_Start();
	WriteI2CByte(0xa0);
	acktemp=Check_Acknowledge();
	WriteI2CByte(addr);
	acktemp=Check_Acknowledge();
	WriteI2CByte(thedata);
	acktemp=Check_Acknowledge();
	I2C_Stop();

} */

void Write_A_Page(uchar *buffer,uchar addr)
{
	bit acktemp=1;
	uchar i;
	/*write a page to at24c02*/
	I2C_Start();
	WriteI2CByte(0xa0);
	acktemp=Check_Acknowledge();
	WriteI2CByte(addr);/*address*/
	acktemp=Check_Acknowledge();
	for(i=0;i<8;i++)
	{
	WriteI2CByte(buffer[i]);
	if(!Check_Acknowledge())
	    {
	        I2C_Stop();
	    }
	}
	I2C_Stop();
}

/*uchar Read_One_Byte(char addr)
{        
	bit acktemp=1;
	uchar mydata;

	I2C_Start();
	WriteI2CByte(0xa0);
	acktemp=Check_Acknowledge();
	WriteI2CByte(addr);
	acktemp=Check_Acknowledge();
	
	I2C_Start();
	WriteI2CByte(0xa1);
	acktemp=Check_Acknowledge();  
	
	
	mydata=ReadI2CByte();
	acktemp=Check_Acknowledge();
	I2C_Stop();

	return mydata;
}	*/

void Read_N_Bytes(uchar *buffer,uchar k,uchar addr)
{
	bit acktemp=1;
	
	uchar i=0;
	/*read 8 bytes from mem*/
	I2C_Start();
	WriteI2CByte(0xa0);
	acktemp=Check_Acknowledge();
	WriteI2CByte(addr);/*address*/	
	acktemp=Check_Acknowledge();
	I2C_Start();
	WriteI2CByte(0xa1);	
	acktemp=Check_Acknowledge();
	for(i=0;i<k;i++)
	{
	    buffer[i]=ReadI2CByte();
	    if(i!=k-1)
	        SEND_0();    /*发送应答*/
	    else
	        SEND_1();    /*发送非应答*/
	}
	
	I2C_Stop();
}

void main(void)
{
	uchar i;
	uchar t;
	PCON=0x00;
	SCON=0x90;
	EA=1;
	ES=1;
	led_yellow=0;//信号接收灯亮

	TorR=0;//允许接收
	ldelay(1);	 //短延时
	if(TorR)			 //判断是否接受到数据
	{
		do
		{
			for(i=0;i<n;i+=8)
				Write_A_Page(rdata+i,0x00+i+(72*times));//写EEPROM
			counter=0;
			totalnum=0;
			times++;
			TorR=0;
			if(times<3)while(TorR==0);	//写三次即可
		}while(times<3);
		led_yellow=1;//信号接收灯灭
		ldelay(15);
	}
	led_yellow=1;
	ldelay(2);
	TorR=1;	 //接收停止,开始发送
	led_green=0;
	TB8=0;
	SBUF=0x00;	  //reset-code	 复位码
	while(TI==0);TI=0;
	
	while(1)
	{
		T_D=0;
		for(i=70;i>0;i--);//delay 100 us
		T_D=1;
		for(i=7;i>0;i--);//delay 10 us
		
		TB8=1;
		SBUF=0x00;	  //start-code	   起始码
		while(TI==0);TI=0;
		for(t=0;t<32;t++)		   //共控制32台灯具
		{
			Read_N_Bytes(rdata,7,0x00+(t<<2)+(t<<1));//读取每台灯命令 共六个通道
			for(i=1;i<7;i++)
			{
				TB8=1;
				SBUF=rdata[i];
				while(TI==0);TI=0;
			}
		}
	}	
}
/*串口中断响应函数*/
void receive(void) interrupt 4 using 2
{
    if(RI==1)/*如果是接收中断*/
    {
		if(!RB8)flag=1;		  //复位帧即置标志位
        else if(flag&&((totalnum++/72)==times))	//每次读取72字节,分三次读取
        {
        	rdata[counter++] =SBUF;
        	if(counter==n)	  //读取72字节至缓冲区,暂停接收
				TorR=1;
        }
 		RI=0;/*清除中断标志位,允许下一次中断*/
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -