2 jd chuying1990 jd_chuying1990 于 2014.05.04 19:59 提问

51单片机模拟spi控制电力载波芯片MI200E,发送0xaa,接收有显示,但不是0xaa。

想测试发送0xaa,但接收不对,而且接收更像是乱码,改了很多地方都不对,不知道问题出在哪里,希望各位大神帮忙看看代码错在哪。我用的keil3编译环境,51单片机,电力线载波芯片是MI200E,测试接收0xaa是通过8个led灯(也用串口显示过,和led灯显示相匹配)第一次提问题,不知道怎么把MI200E的数据手册和应用手册贴出来,在代码后贴出了文档在百度文库上的网址,麻烦各位大神了,小弟这次是碰到棘手困难了,在这先谢了。代码如下:
/********发送程序*********************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
//sbit MOSI=P1^0; //主设备发送从设备接收线,master output subordinate input
//sbit MISO=P1^1; //从设备发送主设备接收线 master input subordinate output
sbit SDO=P1^2; //p1.3口模拟主机输出 主设备发送从设备接收
sbit SDI=P1^1; //p3.2口模拟主机输入,接到外部中断0 主设备接收从设备发送
sbit sck=P1^3; //SPI时钟
sbit cs=P1^4; //片选 p1.3
sbit MI200E_RST=P1^5; //复位
sbit ceshi1=P0^6;
sbit ceshi2=P0^7;

uchar num;
uchar RDSR_command; //用来读0x82

uchar CRC_H,CRC_L;
uchar step,i;

void delay(uint z);//延时
void cudelay_50us();
void init_MI200E();//初始化
void Write_CommandReg(uchar add,uchar com);//写控制指令
uchar Read_CommandReg(uchar add);//读控制指令
void Write_DataReg(uchar add,uchar dat);//写数据,dat应是16位的
void Write_DataReg2(uchar add,uchar dat_H,uchar dat_L);//改进,将高低8位分开发送
uchar Read_DataReg(uchar add);//读数据
void send();

void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}

void cudelay_50us()
{
uchar i;
for(i=0;i<5;i++);
}

void init_MI200E() //初始化
{
MI200E_RST=0;
delay(600); //要求延时超过500ms
MI200E_RST=1;
delay(60); //要求延时超过50ms
Write_CommandReg(0x01,0xFF);
Write_CommandReg(0x0C,0x58);

    Write_CommandReg(0x0D,0x01);         //应用笔记这样写

// Write_CommandReg(0x0D,0x0A); //数据手册这样写

    Write_CommandReg(0x10,0x66);
    Write_CommandReg(0x12,0x66);
    Write_CommandReg(0x14,0x66);
    Write_CommandReg(0x11,0x88);
    Write_CommandReg(0x13,0x88);
    Write_CommandReg(0x15,0x88);
    Write_CommandReg(0x07,0xFF);
    Write_CommandReg(0x0A,0x00);
    Write_CommandReg(0x0B,0x00);

}

void init()
{
TMOD=0x01;//设置定时器0工作方式1
TH0=(65536-2293)/256;//定时5ms
TL0=(65536-2293)%256;
EA=1;
ET0=1;//开定时器0
TR0=1;//启动定时器0

}

//写入控制寄存器
void Write_CommandReg(uchar add,uchar com)
{

    uchar i;
    uchar mark;
    cs=0;
    mark=0x80;
    _nop_();                       //_nop_();延时1us
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;
            }
            else
            {
                    SDO=0;
           }
            sck=1;
            _nop_();
     mark>>=1;
    }
    mark=0x80;
    for(i=0;i<8;i++)
    {
            sck=0;
                        _nop_();
            if(com&mark)
            {
                    SDO=1;
            }
            else
            {
                    SDO=0;
            }

            sck=1;
            _nop_();
            mark>>=1;
    }
    _nop_();
            sck=0;
    cs=1;

}

//读取控制寄存器
uchar Read_CommandReg(uchar add) //时序有问题,返回的readdata有三个高,目测是TI、carr和
{ //Frame,但P2口值检测出Frame为高

    uchar i;
    uchar mark;
    uchar readdata;
    cs=0;
    mark=0x80;

    _nop_();
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
//                      _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
                    _nop_();
            mark>>=1;
    }

    _nop_();
    _nop_();    
    for(i=0;i<8;i++)
    {       //此处不能加延时             
            sck=0;
            _nop_();
            readdata<<=1;               
            if(SDI)
            {       
                    readdata|=1;        
            }
            else
            {
                    readdata&=0xFE;
            }

            sck=1;
            _nop_();


    }
    _nop_();
    sck=0;
    _nop_();

    cs=1;

    return(readdata);

}

//写入数据寄存器

void Write_DataReg(uchar add,uchar dat)
{

    uchar i;
    uchar mark;
    uchar marklong;
    cs=0;
    mark=0x80;
    marklong=0x8000;
    _nop_();
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
            _nop_();

            mark>>=1;
    }

    for(i=0;i<16;i++)
    {
            sck=0;
            _nop_();

            if(dat&marklong)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }

            sck=1;
            _nop_();
     marklong>>=1;
    }
    _nop_();
            sck=0;
    cs=1;

}

void Write_DataReg2(uchar add,uchar dat_H,uchar dat_L)
{
uchar i;
uchar mark;
uint marklong;
cs=0;
mark=0x80;
marklong=0x8000;
nop();
nop();

for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(add&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }
    sck=1;
    _nop_();

    mark>>=1;
}

for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(dat_H&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }

    sck=1;
    _nop_();
    mark>>=1;
}
for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(dat_L&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }

    sck=1;
    _nop_();
    mark>>=1;
} 

 _nop_();
 sck=0;
cs=1;

}

//读取数据寄存器
uchar Read_DataReg(uchar add)
{

    uchar i;
    uchar mark;
    uint readdata;
    cs=0;
    mark=0x80;
    readdata=0;
    _nop_();
    _nop_();
    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
            _nop_();

            mark>>=1;
    }
    _nop_();
    _nop_();
    for(i=0;i<16;i++)
    {

            sck=0;
            _nop_();
            readdata<<=1;
            if(SDI)
            {
                    readdata|=1;
            }
            else
            {
                    readdata&=0xFE;

            }
            sck=1;

            _nop_();

    }
    _nop_();
            sck=0;
    cs=1;
    return(readdata);

}

void send()
{
// Write_CommandReg(0x01,0x01); //bit6~4扩频码字,bit3~2波特率选择,bit1~0载波频率
//配置进入发送状态
switch(step)
{
case 0:
{
Write_CommandReg(0x01,0x0d);//将0x01的bit2、3至高,其余不变,以最低速率发送bit2、3
// Write_CommandReg(0x02,0x00);//将TI复位
Write_DataReg2(0x04,0xff,0xff); //发送0xff,0xff引导码
step=1;
}
break;
case 1:
{
Write_CommandReg(0x02,0xfd);//将0x02的CRC清零
// Write_CommandReg(0x02,0x00);//将TI复位
Write_DataReg2(0x04,0x1a,0x0c);//发送bit3 0x1a和bit4 波特率和长度
step=2;
}
break;
case 2:
{
Write_CommandReg(0x01,0x01);//将bit2、3恢复原设波特率1600和76.8kHZ
// Write_CommandReg(0x02,0x00);//将TI复位
Write_DataReg(0x04,0xaa);//发送bit5,即使改成0xaaaa也不对

        for(i=0;i<10;i++)       //延时50us
        {
            _nop_(); _nop_();   _nop_();    _nop_();    _nop_();
        }
        CRC_H=Read_CommandReg(0xa8);  //读CRC
        CRC_L=Read_CommandReg(0xa9);
        step=3;
    }
    break;
    case 3:
    {

// Write_CommandReg(0x02,0x00);//将TI复位
Write_DataReg2(0x04,CRC_H,CRC_L);//发送CRC
step=0;

    }
    break;
    default:
    {delay(10);}
    break;

}

}

void main()
{
init();
init_MI200E();
Write_CommandReg(0x02,0x80);
Write_DataReg2(0x04,0xff,0xff);
Write_CommandReg(0x01,0x01); //bit6~4扩频码字,bit3~2波特率选择,bit1~0载波频率
step=0;
sck=0;
SDI=1;
while(1);

}

void timer0() interrupt 1//2.5ms
{
// P1|=1;
TH0=(65536-2293)/256;//
TL0=(65536-2293)%256;//重装初值
// Write_CommandReg(0x02,0x80);
RDSR_command=Read_CommandReg(0x82);
P2=RDSR_command;
if((RDSR_command & 0x80)==0x80) //每隔2.5ms查询0x82,判断bit7 TI是否为1
{ ceshi2=0;
// P1&=0xFE;
Write_CommandReg(0x02,0x00);//将TI复位
// delay(5);
send(); //TI为1执行发送,TI为1往发送寄存器写入数据,之后TI需复位
// Write_CommandReg(0x01,0x0d);//将0x01的bit2、3至高,其余不变,以最低速率发送bit2、3
// Write_DataReg2(0x04,0xff,0xff); //发送0xff,0xff引导码

// P1|=1;
// P0=0xaa;
}
// P1&=0xFE;

}

/*************接收程序************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
//sbit MOSI=P1^0; //主设备发送从设备接收线,master output subordinate input
//sbit MISO=P1^1; //从设备发送主设备接收线 master input subordinate output
sbit SDO=P1^2; //p1.3口模拟主机输出 主设备发送从设备接收
sbit SDI=P1^1; //p3.2口模拟主机输入,接到外部中断0 主设备接收从设备发送
sbit sck=P1^3; //SPI时钟
sbit cs=P1^4; //片选 p1.3
sbit MI200E_RST=P1^5; //复位
sbit ceshi1=P0^6;
sbit ceshi2=P0^7;

uchar num;
uchar RDSR_command; //用来读0x82
uchar RDRR_command; //用来读0x83
uchar RDRB0_DataReg; //用来读取数据寄存器0x84

uchar CRC_H,CRC_L,CRC_flag;
uchar step,i;

void delay(uint z);
void cudelay_50us();
void init_MI200E();
void Write_CommandReg(uchar add,uchar com);
uchar Read_CommandReg(uchar add);
void Write_DataReg(uchar add,uchar dat);
void Write_DataReg2(uchar add,uchar dat_H,uchar dat_L);
uchar Read_DataReg(uchar add);
void send();

void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}

void cudelay_50us()
{
uchar i;
for(i=0;i<5;i++);
}

void init_MI200E() //初始化
{
MI200E_RST=0;
delay(600); //要求延时超过500ms
MI200E_RST=1;
delay(60); //要求延时超过50ms
Write_CommandReg(0x01,0xFF);
Write_CommandReg(0x0C,0x58);

    Write_CommandReg(0x0D,0x01);         //应用笔记这样写

// Write_CommandReg(0x0D,0x0A); //数据手册这样写

    Write_CommandReg(0x10,0x66);
    Write_CommandReg(0x12,0x66);
    Write_CommandReg(0x14,0x66);
    Write_CommandReg(0x11,0x88);
    Write_CommandReg(0x13,0x88);
    Write_CommandReg(0x15,0x88);
    Write_CommandReg(0x07,0xFF);
    Write_CommandReg(0x0A,0x00);
    Write_CommandReg(0x0B,0x00);

}

void init()
{
TMOD=0x01;//设置定时器0工作方式1
TH0=(65536-2293)/256;//定时5ms
TL0=(65536-2293)%256;
EA=1;
ET0=1;//开定时器0
TR0=1;//启动定时器0

}

//写入控制寄存器
void Write_CommandReg(uchar add,uchar com)
{

    uchar i;
    uchar mark;
    cs=0;
    mark=0x80;
    _nop_();                       //_nop_();延时1us
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;
            }
            else
            {
                    SDO=0;
           }
            sck=1;
            _nop_();
     mark>>=1;
    }
    mark=0x80;
    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();
            if(com&mark)
            {
                    SDO=1;
            }
            else
            {
                    SDO=0;
            }

            sck=1;
            _nop_();
            mark>>=1;
    }
    _nop_();
            sck=0;
    cs=1;

}

//读取控制寄存器
uchar Read_CommandReg(uchar add)
{

    uchar i;
    uchar mark;
    uchar readdata;
    cs=0;
    mark=0x80;

    _nop_();
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
//                      _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
                    _nop_();
            mark>>=1;
    }

    _nop_();

    for(i=0;i<8;i++)
    {       //此处不能加延时             
            sck=0;
            _nop_();
            readdata<<=1;               
            if(SDI)
            {       
                    readdata|=1;        
            }
            else
            {
                    readdata&=0xFE;
            }

            sck=1;

// nop();

    }
    _nop_();
    sck=0;
    _nop_();

    cs=1;

    return(readdata);

}

//写入数据寄存器

void Write_DataReg(uchar add,uchar dat)
{

    uchar i;
    uchar mark;
    uchar marklong;
    cs=0;
    mark=0x80;
    marklong=0x8000;
    _nop_();
    _nop_();

    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
            _nop_();

            mark>>=1;
    }

    for(i=0;i<16;i++)
    {
            sck=0;
            _nop_();

            if(dat&marklong)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }

            sck=1;
            _nop_();
     marklong>>=1;
    }
    _nop_();
            sck=0;
    cs=1;

}

void Write_DataReg2(uchar add,uchar dat_H,uchar dat_L)
{
uchar i;
uchar mark;
uint marklong;
cs=0;
mark=0x80;
marklong=0x8000;
nop();
nop();

for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(add&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }
    sck=1;
    _nop_();

    mark>>=1;
}

for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(dat_H&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }

    sck=1;
    _nop_();
    mark>>=1;
}
for(i=0;i<8;i++)
{
    sck=0;
    _nop_();

    if(dat_L&mark)
    {
        SDO=1;

    }
    else
    {
        SDO=0;

    }

    sck=1;
    _nop_();
    mark>>=1;
} 

 _nop_();
 sck=0;
cs=1;

}

//读取数据寄存器
uchar Read_DataReg(uchar add)
{

    uchar i;
    uchar mark;
    uint readdata;
    cs=0;
    mark=0x80;
    readdata=0;
    _nop_();
    _nop_();
    for(i=0;i<8;i++)
    {
            sck=0;
            _nop_();

            if(add&mark)
            {
                    SDO=1;

            }
            else
            {
                    SDO=0;

            }
            sck=1;
            _nop_();

            mark>>=1;
    }
    _nop_();
    _nop_();
    for(i=0;i<16;i++)
    {

            sck=0;
            _nop_();
            readdata<<=1;
            if(SDI)
            {
                    readdata|=1;
            }
            else
            {
                    readdata&=0xFE;

            }
            sck=1;

            _nop_();

    }
    _nop_();
            sck=0;
    cs=1;
    return(readdata);

}

void send()
{
// Write_CommandReg(0x01,0x01); //bit6~4扩频码字,bit3~2波特率选择,bit1~0载波频率
//配置进入发送状态
switch(step)
{
case 0:
{
Write_CommandReg(0x01,0x0d);//将0x01的bit2、3至高,其余不变,以最低速率发送bit2、3
Write_DataReg2(0x04,0xff,0xff); //发送0xff,0xff引导码
step=1;
}
break;
case 1:
{
Write_CommandReg(0x02,0xfd);//将0x02的CRC清零
Write_DataReg2(0x04,0x1a,0x0c);//发送bit3 0x1a和bit4 波特率和长度
step=2;
}
break;
case 2:
{
Write_CommandReg(0x01,0x01);//将bit2、3恢复原设波特率1600和76.8kHZ
Write_DataReg(0x04,0xaa);//发送bit5
for(i=0;i<10;i++) //延时50us
{
nop(); nop(); nop(); nop(); nop();
}
CRC_H=Read_CommandReg(0xa8); //读CRC
CRC_L=Read_CommandReg(0xa9);
step=3;
}
break;
case 3:
{
Write_DataReg2(0x04,CRC_H,CRC_L);//发送CRC
ceshi1=1;
ceshi2=0;
Write_CommandReg(0x02,0x00);//将TI复位
step=0;
}
break;
default:
{}
break;

}       

}

void receive()
{
switch(step)
{
case 0:
{
RDRR_command=Read_CommandReg(0x83);
if(RDRR_command!=0x00)
{
Write_CommandReg(0x01,0x81);
step=1;

        }   
    }
    break;
    case 1:
    {
        if((RDSR_command & 0x40)==0x40)
        {
            step=2;

        }
        else
        {
            step=1;
        }

    }
    break;
    case 2:
    {
        Write_CommandReg(0x02,0x7a);//将CRC标志位置1
        RDRB0_DataReg=Read_DataReg(0x84);//读取0x84
        Write_CommandReg(0x02,0x30);//将RI清零
        P0=RDRB0_DataReg;
        step=3;
    }
    break;
    case 3:
    {
        CRC_flag=Read_DataReg(0x84);//读取CRC校验标志位

// P0=CRC_flag;
if(CRC_flag==1)
{
Write_CommandReg(0x02,0x00);//将EPF和CRC标志位清零

}

    }
    break;
    default:
    {}
    break;

}   

}
void main()
{
init();
init_MI200E();
// Write_CommandReg(0x02,0x80);

        Write_CommandReg(0x02,0x00);

    Write_CommandReg(0x01,0x81);//bit6~4扩频码字,bit3~2波特率选择,bit1~0载波频率

    Write_CommandReg(0x01,0x8d);//配置接收状态

    step=0;
    sck=0;
    SDI=1;

    while(1);   

}

void timer0() interrupt 1//2.5ms
{
// P1|=1;
TH0=(65536-2293)/256;//
TL0=(65536-2293)%256;//重装初值

RDSR_command=Read_CommandReg(0x82);
P2=RDSR_command;
if(((RDSR_command & 0x20)==0x20)&&((RDSR_command & 0x10)==0x10))   //每隔2.5ms查询0x82,判断carr和frame是否为1
{

// P1&=0xFE;
// Write_CommandReg(0x02,0x00);//将TI复位
// delay(2.5);

        receive();                     //carr和frame为1执行接收
//  cudelay_50us();

// ceshi2=0;
// Write_CommandReg(0x02,0x30);//将RI清零
//Write_DataReg2(0x04,0xff,0xff);
// P1|=1;
// P0=0xaa;
}
// P1&=0xFE;

}

MI200E数据手册网址:CSDN移动问答

MI200E应用笔记网址:CSDN移动问答

3个回答

jipingyuan
jipingyuan   2014.05.04 20:31

你这个程序好长……
挑点儿重点的就可以了

softwoker
softwoker   2015.03.09 17:37

每次发送数据之前都要检查TI是否为1吧!

qq_31222183
qq_31222183   2017.05.02 14:59

兄弟的问题解决没?我现在也碰到和您相同的问题了,不知道如何解决了,希望提供帮助,谢谢,qq:809718131

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!