zoukankan      html  css  js  c++  java
  • MI200e电力线通讯

    最近做课设,选了电力线通讯这种途径,经过百度google等一番查询,最终敲定了mi200e这块国产芯片。


    课设要求就是双机通讯,互传传感器信息以及模拟一个时钟


    然后淘宝买了拆机的成品,我拿回来把mcu拆了然后飞出通讯端口和stm8交互。现在串口两边可以通讯了,下一步就是重新绘制一块完整的pcb,然后制版,并实现响应功能。

    先上ref:

    http://search.eefocus.com/s?app_id=90&sub=1&q=mi200e

    这是电路城搜索mi200e得出的结果,我主要参考第一篇,他在嘉立创还有发帖,点进去你就找得到了。

    他使用stm8主控并绘制整块pcb,我则使用以前的stm8核心小板。由于mi200e常规供电为5v,稍稍更改核心板为5v供电做好。

    没有拍当时做的图片,上pcb和实物吧!

    将右图放大后,可看到两块绿板,这两块就是成品模块,应用于智能抄表的。可看到左边那块上有一根小跳线,跳线右边哪里原来是块u,我用烙铁把他拆了。

    不然stm8没法单独和mi200e通讯。至于为什么要跳那根线,我在网上恰好查到他的原理图,(应该是miartech官方的方案,然后抄的,原件丝印不同),mi200e的供电vdd受一个pmos控制,

    所以直接将mos的g级接地。其实我买了两种,一共买了四块,连运费20+rmb。另一种的丝印是和原理图队上的。我后面会附上手头的资料。

    两块板子背面其实有排针,原来用于接220v的,我直接把他们并联在一起,然后接了一根电源线。一方面因为我电源线紧张,另一方面固定在一块纸板上方便调试。

     这是原理图,通讯接口是SPI,其中cs不能直接接地,因为数据是双向互传,并且不是单次传输。具体参考SPI接口flash的cs为什么不能直接接地吧。

    我一开始想省io直接接地,结果调试的时候发现,自检过不了。

    至于rst引脚,我把它接到stm8的nrst恰好可以使用,虽然官方应用笔记里面说要低电平1s后拉高。留待后面再测试吧。

    这样就是4个io就能交互了。


    然后我按照嘉立创那篇帖子里的方案做了,然后一直调试,发现他的程序我直接用不了,数据通。

    然后我发现省略了crc校验初步数据能够发送,但是有毛病。

     没办法,又看手册,看应用笔记。以及对比另一个c51版本的程序

    ,这个程序从我给的链接里的第二篇可以下载到。但是这个只是驱动,应该就是这个产品用到的,但是没给全程序。我猜嘉立创那篇帖主

    也是参考这个改的,因为驱动大体一致。我同时看笔记,以及两篇驱动,最后经过一番修改,然后下进去竟然就可以工作了。

    程序限制它64字节,对于一般应用足够了。

    说一下这块芯片的发送过程,两个引导字节(一个字),一个固定字节,然后配置字节(速率和字长,字为单位)。到这里都是固定200/240bps速率(会因交流电频率不同而不同),之后的速率可自行配置,

    程序里设定的是1600/1920bps。然后是以字为单位的数据(这里就是串口透传,由于是字对齐,所以必须是偶数字节,这里要注意!),最后一个字的CRC校验。

    附上一张笔记图,看别人的代码真是不容易啊。这里双向能通讯了,后面再看要不要他程序的框架,如果要,还有更多细节要明白。

    和硬件打交道,如果不懂的话,可能就是一个延时你就要消耗大把时间。所以需要日积月累!

      1 #include "stm8s.h"
      2 #include "config.h"
      3 #include "MI200E.h"
      4 #include "PLCProcess.h"
      5 
      6 unsigned char g_cStatusReg;
      7 unsigned char g_cRecModCfgReg;
      8 unsigned short PLC_Word_Rec_Overtime;
      9 unsigned char    g_bRecv_Pkg_Flag;
     10 unsigned char g_CRC_H,g_CRC_L;
     11 unsigned char g_cPkg_Length = 0;
     12 unsigned char g_Pkg_Indication_Byte = 0;
     13 unsigned char g_cTrans_Step;
     14 unsigned char g_cRecv_Step;
     15 unsigned char g_cRecByte_H;
     16 unsigned char g_cRecByte_L;
     17 unsigned char g_cSend_Data_Length;
     18 unsigned char g_cSend_Byte_Cnt;        
     19 unsigned char g_cRecv_Byte_Cnt;
     20 unsigned char g_Send_Buf[64];
     21 unsigned char g_Recv_Buf[64];
     22 
     23 
     24 void PLC_Send_Frame(unsigned char cWRData_H, unsigned char cWRData_L)
     25 {        
     26   PLC_Write_Reg(PLCAddrWRSR,(g_cStatusReg&0x7F)); //Clear TI;Write Status Register:0x02
     27   MI200E_SCK_0;
     28   MI200E_CS_0;
     29   Write_SPI(PLCAddrWRTB0);    //Write Sending Byte Register 0:0x04
     30   Write_SPI(cWRData_H);
     31   Write_SPI(cWRData_L);
     32   MI200E_SCK_0;
     33   MI200E_CS_1;        
     34 }
     35 
     36 void PLC_RD_Recv_Word(void)
     37 {    
     38   MI200E_SCK_0;
     39   MI200E_CS_0;
     40   Write_SPI(PLCAddrRDRB0);    //Read Receiving Byte Register 0:0x84
     41   g_cRecByte_H = Read_SPI();
     42   g_cRecByte_L = Read_SPI();
     43   MI200E_SCK_0;
     44   MI200E_CS_1;
     45 }
     46 
     47 unsigned char PLC_Clear_EPF(void)
     48 {        
     49   unsigned char cStatusByte; 
     50   
     51   cStatusByte = PLC_Read_Reg(PLCAddrRDSR);            //Read Status Register:0x82
     52   PLC_Write_Reg(PLCAddrWRSR, (cStatusByte&0xF5));    //Clear EPF Flag & CRC_Flag;Write Status Register:0x02
     53   return(cStatusByte);
     54 }
     55 
     56 
     57 void PLC_Transmit_Process(unsigned char* ptrData_Buffer)
     58 {
     59   unsigned char cStatusByte;
     60 
     61   cStatusByte = PLC_Read_Reg(PLCAddrRDSR);    //Read status register
     62   if((cStatusByte&0x80) != 0x80)
     63   {    
     64     return;
     65   }
     66   g_cStatusReg = cStatusByte;//**confirmed
     67   switch(g_cTrans_Step)
     68   {    
     69   case 0:
     70     //Write Mode Cfg Reg, Code Length = 32, Data Rate = 200 bps;
     71     PLC_Write_Reg(PLCAddrWRMR, 0x0D); //**0x0d changed to 0x0c;diff:carriar freq:76.5->57.6khz             
     72     PLC_Send_Frame(0xFF, 0xFF);     //First 2 Byte:0xFF 0xFF
     73     //Baud=1600bps + length(unit in words)
     74     g_Pkg_Indication_Byte = (0x00 + g_cSend_Data_Length/2 + 2);//**why finially +2??
     75     g_cTrans_Step = 1;
     76   break;
     77   case 1:
     78     //Initial CRC Bit;Write Status Register:0x02
     79     PLC_Write_Reg(PLCAddrWRSR,(g_cStatusReg & 0xFD));
     80     //Send Header Byte:0x1a & Packet Indication Byte 
     81     PLC_Send_Frame(0x1A, g_Pkg_Indication_Byte); 
     82     g_cTrans_Step = 2;
     83   break;    
     84   case 2:
     85     //Write mode configuration;
     86     PLC_Write_Reg(PLCAddrWRMR,0x01);//0b0000  00--1600/1920bps  01--76.8khz**00 57.6k
     87     //Send 0x1f,0xff as MiarTech's PLC AMR Applications
     88     PLC_Send_Frame(0x1F,0xFF);//**the word??
     89     g_cTrans_Step = 3;
     90     g_cSend_Byte_Cnt = 0;
     91   break;
     92   case 3://Send Data(Unit in Word:16 Bytes)
     93     if(g_cSend_Byte_Cnt >= (g_cSend_Data_Length - 2))    
     94     {    
     95       g_cTrans_Step = 4;
     96     }
     97     PLC_Send_Frame(*ptrData_Buffer,*(ptrData_Buffer + 1));
     98     g_cSend_Byte_Cnt = g_cSend_Byte_Cnt + 2;//point to the next word
     99     delay_us(80);//delay 50us and read crc
    100     g_CRC_H = PLC_Read_Reg(PLCAddrRD_CRC_H);    
    101     g_CRC_L = PLC_Read_Reg(PLCAddrRD_CRC_L);
    102   break;
    103   case 4://Send CRC Code:16 Bytes
    104     PLC_Send_Frame(g_CRC_H, g_CRC_L);
    105     g_cTrans_Step = 5;
    106   break;
    107   case 5://transmit finished   0x81
    108     PLC_Write_Reg(PLCAddrWRMR, 0x81);    //Write mode configuration, 
    109     g_cRecByte_H        = 0;            
    110     g_cRecByte_L        = 0;    
    111     g_cRecv_Step        = 0x00;
    112     PlcRunMode = PLCRX;  
    113     UartRunMode = IDLE;
    114   break;
    115   default:    
    116   break;
    117   }
    118 }
    119 
    120 
    121 void PLC_Receive_Process(unsigned char* ptrData_Buffer)
    122 {
    123   unsigned char cStatusByte;
    124   unsigned char CRC_Correct_Flag;
    125 //  unsigned char temp,i;
    126 //  static unsigned short cnt;
    127 
    128   
    129   if(g_cRecv_Step == 0x10)//Receive Process Initialization OK
    130   {    
    131     g_cRecModCfgReg = PLC_Read_Reg(PLCAddrRDRR);    //Read Receiving Mode Configuration Register(0x83)
    132     cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
    133     if(g_cRecModCfgReg != 0x00)    //Have Received Spread Spectrum&Packet Length
    134     {    
    135         PLC_Write_Reg(PLCAddrWRRR,0x00);        //Clear Receiving Mode Configuration Byte                    
    136         g_cPkg_Length = (0x3f & g_cRecModCfgReg);    //Packet Length = g_cRecModCfgReg[5:0]  
    137         g_cRecv_Step = 0x01;
    138         PLC_Word_Rec_Overtime = 0;
    139     }    
    140     if(((cStatusByte & 0x30) != 0x30)||(PLC_Word_Rec_Overtime > 500)) //Receive Overtime >=1 Second
    141     {
    142         CRC_Correct_Flag = PLC_Clear_EPF();
    143         g_cRecv_Step = 0x00;
    144         return;
    145     }
    146   }
    147   else if(g_cRecv_Step == 0x00)
    148   {                            //0x81
    149     PLC_Write_Reg(PLCAddrWRMR, 0x81);//bit[0]--bit[3]  00--1600/1920bps  01--76.8khz
    150     cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
    151     g_cStatusReg = cStatusByte;
    152     if((g_cStatusReg & 0x20 ) == 0x20)//Read Carrier Detected Flag
    153     {    
    154       if((g_cStatusReg & 0x10) == 0x10)//Read Frame Indicate Flag                
    155       {    
    156           //Clear Receiving Mode Configuration Byte
    157           //PLC_Write_Reg(PLCAddrWRRR, 0x00);//datasheet??
    158           g_bRecv_Pkg_Flag = 0;//*(*?
    159           g_cRecv_Step = 0x10;
    160           PLC_Word_Rec_Overtime = 0;                    
    161       }                        
    162     }
    163   }  
    164   else
    165   {    
    166     cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
    167     g_cStatusReg = cStatusByte;
    168 
    169      //Carrier Detected & Frame Indicate Flag is not Correct
    170     if(((cStatusByte & 0x30) != 0x30)||(PLC_Word_Rec_Overtime > 500))
    171     {
    172       g_cRecv_Step = 0x00;
    173       CRC_Correct_Flag = PLC_Clear_EPF();
    174       return;
    175     }    
    176     else 
    177     {
    178       if((cStatusByte & 0x40) == 0x40)//Read Received Interrupt Flag.RI = 1:Received OK    
    179       {    
    180         PLC_Word_Rec_Overtime = 0;
    181 //        if(cnt == 0)
    182         {
    183             PLC_Write_Reg(PLCAddrWRSR,((g_cStatusReg & 0xBF)|0x02)); //Clear RI Flag & Set MI200_CRC
    184         }
    185         switch( g_cRecv_Step )
    186         {    
    187           case 0x01:    //Read 0x1f,0xff as MiarTech's PLC AMR Applications
    188           {    
    189 //            cnt ++;
    190 //            if(cnt > 20)
    191 //            {
    192 //              cnt = 0;
    193 //              g_cRecv_Step = 0x00;  
    194 //              return;                                                               
    195 //            }
    196 //            temp = PLC_Read_Reg(PLCAddrRDSR);                                                             
    197 //            if((temp&0x70) != 0x70)
    198 //              return;
    199 //            cnt = 0;
    200 //            
    201             PLC_RD_Recv_Word();
    202             if((g_cRecByte_H == 0x1F) && (g_cRecByte_L == 0xFF))    
    203             {    
    204               g_cRecv_Step = 0x02;
    205               g_cRecv_Byte_Cnt = 0;
    206             }
    207             else    
    208             {    
    209               g_cRecv_Step = 0x00;
    210               CRC_Correct_Flag = PLC_Clear_EPF();
    211               return;
    212             }
    213           }    
    214           break;                
    215           case 0x02: //read user data
    216           {     
    217 //            if(cnt == 0)
    218 //            {
    219 //                PLC_Write_Reg(PLCAddrWRSR,((g_cStatusReg & 0xBF )|0x02)); //Clear RI Flag & Set MI200_CRC
    220 //            } 
    221 //            cnt ++;
    222 //            if(cnt > 20)
    223 //            {
    224 //              cnt = 0;
    225 //              g_cRecv_Step = 0x00;  
    226 //              return;                                                               
    227 //            }
    228 //            temp = PLC_Read_Reg(PLCAddrRDSR);                                                             
    229 //            if((temp&0x70) != 0x70)
    230 //              return;
    231 //            cnt = 0;
    232             
    233             if(g_cRecv_Byte_Cnt == (g_cPkg_Length - 3))    //1 for amr;1 for crc
    234             {    
    235               g_cRecv_Step = 0x03;    
    236             }
    237             PLC_RD_Recv_Word();
    238             
    239             *(ptrData_Buffer + g_cRecv_Byte_Cnt) = g_cRecByte_H;
    240             *(ptrData_Buffer + g_cRecv_Byte_Cnt + 1) = g_cRecByte_L;
    241             
    242             g_cRecv_Byte_Cnt++ ;
    243           }    
    244           break;
    245           case 0x03: //读取CRC数据
    246 //            cnt ++;
    247 //            if(cnt > 20)
    248 //            {
    249 //              cnt = 0;
    250 //              g_cRecv_Step = 0x00;  
    251 //              return;                                                               
    252 //            }
    253 //            temp = PLC_Read_Reg(PLCAddrRDSR);                                                             
    254 //            if((temp&0x70) != 0x70)
    255 //              return;
    256 //            cnt = 0;
    257             
    258             PLC_RD_Recv_Word();
    259             CRC_Correct_Flag = PLC_Clear_EPF();
    260             g_bRecv_Pkg_Flag = 1;
    261             if ((CRC_Correct_Flag & 0x02) != 0x00) //CRC Flag Bit = 1;CRC is Correct 
    262             {
    263               //串口发送
    264               UartRunMode = TX;
    265               unsigned char txlen;
    266               txlen = (g_cPkg_Length-2)*2;
    267               UsatrTxSub(g_Recv_Buf,txlen); 
    268               UartRunMode = IDLE;
    269             }
    270            g_cRecv_Step = 0x04;
    271           break;
    272           default:    
    273           break;
    274         }
    275       }
    276     } 
    277   }
    278 } 
    279 
    280 
    281 /*******************************************************************************
    282 **                                  End Of File                                  
    283 *******************************************************************************/
    View Code

    主要修改的就是,这个文件了。后面有什么进展还会更新!


     10/14日更新!

    期间参照它的工程做了修改,重画原理图pcb,然后做手工板。

    做了两块,对齐的一般但是能用,只是两块板硬件调试都花了很长时间。

    第一块是花原理图的时候中间有个电容连线错了,参照成品一个原件一个原件对,找了很久。由于画图的时候,他在原理图边上,没注意它。

    第二块是焊接一个电容,它可能被我烫坏了,造成mi200e经常开机过不了自检,也是图省事全部原件基本都是直接拆的成品上的,最后还是电容一个一个换下来才找到问题。

    这里吸取教训,小电容再也不用拆机的!


    上图:

     实物:

    top layer:(其实这面画的是bottom layer)

    做出来有两个缺陷,一是该也不该用核心板,该是说方便更换,不该就是焊接很难受,布线也不好看,还变大了,不然可以小不少。

    二就是oled,原来考虑是top layer就做最终顶层的,但是寻思直插放另一面合适,最终就把bottom当了顶层。这就导致oled必须换个方向插,

    进而就得让它支出来。

    目前串口透传OK!距离尚未测试。

    按键扫描OK!

    OLED显示OK!

    DS18b20(暂定传感器)程序写了,尚未测试,拿出以前的18b20插的时候引脚断了,因为生锈了。233

    剩下的就是小结构以及模拟一个时钟


    更新:2018年11月13日14:05:17 

    课设快结束了,器件程序调试了好几次,最终基本实现了功能。

    调试时遇到主要BUG:

    发送的数据不能是奇数字节,不然无法正常通信->改为偶数之后正常

    原B板存在MI200E初始化失败情况,反复初始化之后一旦正确就一直正确-> 尝试过原件替换,无果。重新做了一块板,问题解决!


    限于mcu的flash只有8k,导致程序写不下了,所以功能做了调整。

    最终(暂定)功能:

    A端:独立显示时间,读取18b20温度通过电力线发给B

    B端:独立显示时间,通过电力线读取数据并显示温度,可以更改时间,可以校准A的时间。

    尚有未完善的问题:如何用定时器精确微秒级延时供18b20使用

    网上参考了很多方案,自己也调试了许多,效果都不理想。

    最终使用原子的汇编延时,较准确。

    这个问题留待后期解决。

    由于没有铜柱,我简单打印了一个外壳(图里没有体现)。2333

  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/katachi/p/9693077.html
Copyright © 2011-2022 走看看