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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM