最近做课设,选了电力线通讯这种途径,经过百度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校验。

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

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

 #include "stm8s.h"
#include "config.h"
#include "MI200E.h"
#include "PLCProcess.h" unsigned char g_cStatusReg;
unsigned char g_cRecModCfgReg;
unsigned short PLC_Word_Rec_Overtime;
unsigned char g_bRecv_Pkg_Flag;
unsigned char g_CRC_H,g_CRC_L;
unsigned char g_cPkg_Length = ;
unsigned char g_Pkg_Indication_Byte = ;
unsigned char g_cTrans_Step;
unsigned char g_cRecv_Step;
unsigned char g_cRecByte_H;
unsigned char g_cRecByte_L;
unsigned char g_cSend_Data_Length;
unsigned char g_cSend_Byte_Cnt;
unsigned char g_cRecv_Byte_Cnt;
unsigned char g_Send_Buf[];
unsigned char g_Recv_Buf[]; void PLC_Send_Frame(unsigned char cWRData_H, unsigned char cWRData_L)
{
PLC_Write_Reg(PLCAddrWRSR,(g_cStatusReg&0x7F)); //Clear TI;Write Status Register:0x02
MI200E_SCK_0;
MI200E_CS_0;
Write_SPI(PLCAddrWRTB0); //Write Sending Byte Register 0:0x04
Write_SPI(cWRData_H);
Write_SPI(cWRData_L);
MI200E_SCK_0;
MI200E_CS_1;
} void PLC_RD_Recv_Word(void)
{
MI200E_SCK_0;
MI200E_CS_0;
Write_SPI(PLCAddrRDRB0); //Read Receiving Byte Register 0:0x84
g_cRecByte_H = Read_SPI();
g_cRecByte_L = Read_SPI();
MI200E_SCK_0;
MI200E_CS_1;
} unsigned char PLC_Clear_EPF(void)
{
unsigned char cStatusByte; cStatusByte = PLC_Read_Reg(PLCAddrRDSR); //Read Status Register:0x82
PLC_Write_Reg(PLCAddrWRSR, (cStatusByte&0xF5)); //Clear EPF Flag & CRC_Flag;Write Status Register:0x02
return(cStatusByte);
} void PLC_Transmit_Process(unsigned char* ptrData_Buffer)
{
unsigned char cStatusByte; cStatusByte = PLC_Read_Reg(PLCAddrRDSR); //Read status register
if((cStatusByte&0x80) != 0x80)
{
return;
}
g_cStatusReg = cStatusByte;//**confirmed
switch(g_cTrans_Step)
{
case :
//Write Mode Cfg Reg, Code Length = 32, Data Rate = 200 bps;
PLC_Write_Reg(PLCAddrWRMR, 0x0D); //**0x0d changed to 0x0c;diff:carriar freq:76.5->57.6khz
PLC_Send_Frame(0xFF, 0xFF); //First 2 Byte:0xFF 0xFF
//Baud=1600bps + length(unit in words)
g_Pkg_Indication_Byte = (0x00 + g_cSend_Data_Length/ + );//**why finially +2??
g_cTrans_Step = ;
break;
case :
//Initial CRC Bit;Write Status Register:0x02
PLC_Write_Reg(PLCAddrWRSR,(g_cStatusReg & 0xFD));
//Send Header Byte:0x1a & Packet Indication Byte
PLC_Send_Frame(0x1A, g_Pkg_Indication_Byte);
g_cTrans_Step = ;
break;
case :
//Write mode configuration;
PLC_Write_Reg(PLCAddrWRMR,0x01);//0b0000 00--1600/1920bps 01--76.8khz**00 57.6k
//Send 0x1f,0xff as MiarTech's PLC AMR Applications
PLC_Send_Frame(0x1F,0xFF);//**the word??
g_cTrans_Step = ;
g_cSend_Byte_Cnt = ;
break;
case ://Send Data(Unit in Word:16 Bytes)
if(g_cSend_Byte_Cnt >= (g_cSend_Data_Length - ))
{
g_cTrans_Step = ;
}
PLC_Send_Frame(*ptrData_Buffer,*(ptrData_Buffer + ));
g_cSend_Byte_Cnt = g_cSend_Byte_Cnt + ;//point to the next word
delay_us();//delay 50us and read crc
g_CRC_H = PLC_Read_Reg(PLCAddrRD_CRC_H);
g_CRC_L = PLC_Read_Reg(PLCAddrRD_CRC_L);
break;
case ://Send CRC Code:16 Bytes
PLC_Send_Frame(g_CRC_H, g_CRC_L);
g_cTrans_Step = ;
break;
case ://transmit finished 0x81
PLC_Write_Reg(PLCAddrWRMR, 0x81); //Write mode configuration,
g_cRecByte_H = ;
g_cRecByte_L = ;
g_cRecv_Step = 0x00;
PlcRunMode = PLCRX;
UartRunMode = IDLE;
break;
default:
break;
}
} void PLC_Receive_Process(unsigned char* ptrData_Buffer)
{
unsigned char cStatusByte;
unsigned char CRC_Correct_Flag;
// unsigned char temp,i;
// static unsigned short cnt; if(g_cRecv_Step == 0x10)//Receive Process Initialization OK
{
g_cRecModCfgReg = PLC_Read_Reg(PLCAddrRDRR); //Read Receiving Mode Configuration Register(0x83)
cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
if(g_cRecModCfgReg != 0x00) //Have Received Spread Spectrum&Packet Length
{
PLC_Write_Reg(PLCAddrWRRR,0x00); //Clear Receiving Mode Configuration Byte
g_cPkg_Length = (0x3f & g_cRecModCfgReg); //Packet Length = g_cRecModCfgReg[5:0]
g_cRecv_Step = 0x01;
PLC_Word_Rec_Overtime = ;
}
if(((cStatusByte & 0x30) != 0x30)||(PLC_Word_Rec_Overtime > )) //Receive Overtime >=1 Second
{
CRC_Correct_Flag = PLC_Clear_EPF();
g_cRecv_Step = 0x00;
return;
}
}
else if(g_cRecv_Step == 0x00)
{ //0x81
PLC_Write_Reg(PLCAddrWRMR, 0x81);//bit[0]--bit[3] 00--1600/1920bps 01--76.8khz
cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
g_cStatusReg = cStatusByte;
if((g_cStatusReg & 0x20 ) == 0x20)//Read Carrier Detected Flag
{
if((g_cStatusReg & 0x10) == 0x10)//Read Frame Indicate Flag
{
//Clear Receiving Mode Configuration Byte
//PLC_Write_Reg(PLCAddrWRRR, 0x00);//datasheet??
g_bRecv_Pkg_Flag = ;//*(*?
g_cRecv_Step = 0x10;
PLC_Word_Rec_Overtime = ;
}
}
}
else
{
cStatusByte = PLC_Read_Reg(PLCAddrRDSR);
g_cStatusReg = cStatusByte; //Carrier Detected & Frame Indicate Flag is not Correct
if(((cStatusByte & 0x30) != 0x30)||(PLC_Word_Rec_Overtime > ))
{
g_cRecv_Step = 0x00;
CRC_Correct_Flag = PLC_Clear_EPF();
return;
}
else
{
if((cStatusByte & 0x40) == 0x40)//Read Received Interrupt Flag.RI = 1:Received OK
{
PLC_Word_Rec_Overtime = ;
// if(cnt == 0)
{
PLC_Write_Reg(PLCAddrWRSR,((g_cStatusReg & 0xBF)|0x02)); //Clear RI Flag & Set MI200_CRC
}
switch( g_cRecv_Step )
{
case 0x01: //Read 0x1f,0xff as MiarTech's PLC AMR Applications
{
// cnt ++;
// if(cnt > 20)
// {
// cnt = 0;
// g_cRecv_Step = 0x00;
// return;
// }
// temp = PLC_Read_Reg(PLCAddrRDSR);
// if((temp&0x70) != 0x70)
// return;
// cnt = 0;
//
PLC_RD_Recv_Word();
if((g_cRecByte_H == 0x1F) && (g_cRecByte_L == 0xFF))
{
g_cRecv_Step = 0x02;
g_cRecv_Byte_Cnt = ;
}
else
{
g_cRecv_Step = 0x00;
CRC_Correct_Flag = PLC_Clear_EPF();
return;
}
}
break;
case 0x02: //read user data
{
// if(cnt == 0)
// {
// PLC_Write_Reg(PLCAddrWRSR,((g_cStatusReg & 0xBF )|0x02)); //Clear RI Flag & Set MI200_CRC
// }
// cnt ++;
// if(cnt > 20)
// {
// cnt = 0;
// g_cRecv_Step = 0x00;
// return;
// }
// temp = PLC_Read_Reg(PLCAddrRDSR);
// if((temp&0x70) != 0x70)
// return;
// cnt = 0; if(g_cRecv_Byte_Cnt == (g_cPkg_Length - )) //1 for amr;1 for crc
{
g_cRecv_Step = 0x03;
}
PLC_RD_Recv_Word(); *(ptrData_Buffer + g_cRecv_Byte_Cnt) = g_cRecByte_H;
*(ptrData_Buffer + g_cRecv_Byte_Cnt + ) = g_cRecByte_L; g_cRecv_Byte_Cnt++ ;
}
break;
case 0x03: //读取CRC数据
// cnt ++;
// if(cnt > 20)
// {
// cnt = 0;
// g_cRecv_Step = 0x00;
// return;
// }
// temp = PLC_Read_Reg(PLCAddrRDSR);
// if((temp&0x70) != 0x70)
// return;
// cnt = 0; PLC_RD_Recv_Word();
CRC_Correct_Flag = PLC_Clear_EPF();
g_bRecv_Pkg_Flag = ;
if ((CRC_Correct_Flag & 0x02) != 0x00) //CRC Flag Bit = 1;CRC is Correct
{
//串口发送
UartRunMode = TX;
unsigned char txlen;
txlen = (g_cPkg_Length-)*;
UsatrTxSub(g_Recv_Buf,txlen);
UartRunMode = IDLE;
}
g_cRecv_Step = 0x04;
break;
default:
break;
}
}
}
}
} /*******************************************************************************
** End Of File
*******************************************************************************/

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


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

MI200e电力线通讯的更多相关文章

  1. oneM2M标准发展神速 实现万物联网的愿景

    http://m2m.iot-online.com/news/2013102224849.html oneM2M则将负责解决独立于接取网路中通用的M2M服务层的关键需求:使其可更方便地嵌入于各种软硬体 ...

  2. HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术

    最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...

  3. (转)利用libcurl和国内著名的两个物联网云端通讯的例程, ubuntu和openwrt下调试成功(四)

    1. libcurl 的参考文档如下 CURLOPT_HEADERFUNCTION Pass a pointer to a function that matches the following pr ...

  4. (转)linux下和云端通讯的例程, ubuntu和openwrt下实验成功(二)

    前言: 上节用纯linux的函数实现了和云端通讯, 本节开始利用传说中的神器libcurl 话说一个网络程序员对书法十分感兴趣,退休后决定在这方面有所建树. 于是花重金购买了上等的文房四宝.    一 ...

  5. (转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)

    一.  HTTP请求的数据流总结#上传数据, yeelink的数据流如下POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1Host: api. ...

  6. 用SignalR 2.0开发客服系统[系列1:实现群发通讯]

    前言 交流群:195866844 先说一下我为什么会写这个博客吧,(首先说一下,我是一个小菜鸟,讲的不好请指导 - -,)  前段时间公司的项目涉及到在B/S上使用即时通讯,(其实就是做一个B/S的客 ...

  7. 用SignalR 2.0开发客服系统[系列3:实现点对点通讯]

    前言 交流群:195866844 目录: 用SignalR 2.0开发客服系统[系列1:实现群发通讯] 用SignalR 2.0开发客服系统[系列2:实现聊天室] 真的很感谢大家的支持,今天发表系列3 ...

  8. 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(二)

    我们上一篇<基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)>主要讲解了如何搭建一个实时数据通讯服务器,客户端与服务端是如何通讯的,相信通过上一篇的讲解,再配 ...

  9. 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)

    今天没有延续上一篇讲的内容,穿插一段小插曲,WebSocket 实时数据通讯同步的问题,今天我们并不是很纯粹地讲 WebSocket 相关知识,我们通过 WebGL 3D 拓扑图来呈现一个有趣的 De ...

随机推荐

  1. Visual Studio 2015编译wxWidgets

    宫指导说,换帅如换刀 程序员的编译器一换,基本套路必须都重练几次 使用wxWidgets并不难,但不能使用现有的库和工程配置文件,细节就必须理清楚 获取wxWidgets 官方的下载页面,下7z或zi ...

  2. nvm的安装

    安装前可先卸载原来的node, npm, 安装成功后,可用nvm装node 一.用nvm-noinstall.zip安装 1.nvm-windows 下载 https://github.com/cor ...

  3. HTTP状态码--含义

    以下是HTTP状态码(HTTP Status Code)及其解释 1xx(临时响应) (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. (切换协议) 请 ...

  4. java学习之路--继承(子类构造器)

    子类的构造器不能访问父类的私有域,所以必须用的父类的构造器来对这部分的私有域进行初始化,我们可以通过super实现对父类的构造器的调用,使用super调用父类构造器的语句,必须放在子类构造器的第一句. ...

  5. HTML01

    1.什么是HTML?(Hyper Text Markup Language:超文本标记语言) 超文本:功能比普通文本更加强大 标记语言:使用一组标签对内容进行描述的一门语言(它不是编程语言) 2.为什 ...

  6. 微信OAuth授权获取用户OpenId-JAVA(个人经验)【申明:来源于网络】

    微信OAuth授权获取用户OpenId-JAVA(个人经验)[申明:来源于网络] 地址:https://my.oschina.net/xshuai/blog/293458

  7. 最短路径spfa

    #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> ...

  8. npm笔记

    #执行npm start时是运行的哪个js文件? 打开package.json看看scripts属性中start配置的是什么运行脚本,这里配置的就是你执行npm start时跑的脚本 #设置npm的源 ...

  9. 前端paging分页,前端设置每页多少条和当前页面的索引,传给后端,数据显示出来

    1.首先引入jquery 2.在引入paging.css和paging.js  这2个我存在百度云上: 链接:https://pan.baidu.com/s/1SPxlBkkx-pNAtLuRLifE ...

  10. hbase 快速开发

    hbase是一个分布式的NoSQL,部署起来配置很多东西,开发起来太慢,可以使用docker快速搭建环境 gs@gs-virtual-machine:~$ sudo docker run -ti ha ...