📄 main.c
字号:
/* //////////////////////////////////////////////////////////////////////////
// main.c - source file for lme2200 AMR
//
// 家电智能控制统一主机程序(根据UPLM2200 API协议设定)
// Copyright 2006, Leaguer MicroElectronics Co., Ltd
// www.leaguerme.com
//
// 软件修改说明在页底,敬请留意
//////////////////////////////////////////////////////////////////////////// */
#include <REG922.H>
#include "timer.h"
#include "sart.h"
#include "plc.h"
#include "wr_flash.h"
#define uint unsigned int
#define uchar unsigned char
/*============================版本号========================================*/
#define Version1 0x01 //版本号1
#define Version2 0x01 //版本号2
/*=============================================================================*/
#define AMR_OS_C 0 //本协议的控制字在第一位
#define AMR_OS_L 5 //本协议的长度值在第五位
#define S2400 40
#define S1200 50
#define S600 80
uchar code ADSS[4];
uchar plc_frame[18];
uchar code mcu_pc[5]= {0xfe,0xfe,0xfe,0xfe,0x68};
uchar code tx_buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12};
uchar code master = 0;
extern idata uchar amr_frame[]; // AMR frame buffer
extern idata uchar wet;
uchar CRC;//电力网收到CRC的值
extern bit timeout_40s;
extern bit delay_tx;
extern bit packet_recved;
extern bit packet_recving;
extern bit t1_enable;
bit reply;
bit adss_ok;
bit CRC_switch;//CRC开关
void proc_amr_frame(uchar frame[]);
void amr_send_frame(uchar buf[]);
void return_inf(uchar frame,uchar inf_buf[],uchar dat);
void uart_tx_mode(uchar i_buf[]);
void rx_return(bit y,uchar R_data[]);
int plc_send(uchar frame[]);
void return_data();
void adss_crc(uchar buf[]);//地址校验
//void w_flsh(uchar dat,uchar dat1);
/*=============================================================================*/
/* 主程序 */
/*=============================================================================*/
main() {
uchar l;
uchar buf[2];
P0M1 = 0x80; // 这是为第二版电力载波的小模块,发射部分是安捷伦的810方案 -IO口的定义
P0M2 = 0x41;
P1M1 = 0x7c;
P1M2 = 0x80;
Rxok = 0;
timer0_init(242, 10); // 1ms * 10 = 10ms
// plc_init(SMOD_SYNC);
uart_init(); //<--------------串口初始化
//relay_init();
wdt_init();//<----------------看门狗初始化
clr_wdt();
plc_power_on();
for(l = 0;l < 18;l ++)
plc_frame[l] = 0;
clr_wdt();
timeout_40s = 0;
setup_t2(4000, timeout_t2); //原10S
setup_t1(30, disable_t1); //定时LED为300ms
plc_getframe(plc_frame); //查收8300的数据
FLASH_ReadNByte(0x1c00,buf, 2);
if(buf[0]!= 0){
write_reg(REG_WR_33, buf[0]);
write_reg(REG_WR_3c, buf[1]);
}
// FLASH_ReadNByte(0x1b05,buf, 2);
// master_slave = (bit)buf[0];
while (1) { // the forever loop
if (uart_recved()) { // AMR frame recved from meter
disable_t2();//<-------------------------------关40秒定时
if (recv_amr_frame()) { //uart_sendblock(amr_frame,4);
clr_wdt();
// uart_sendblock(amr_frame, amr_frame[5]+6); //串口送至PC
proc_amr_frame(amr_frame); //最多26个字节
clr_wdt();
}
}
if (packet_recving) {//收到电力线上的数据
disable_t2();//<-------------------------------关40秒定时
while (!plc_recved()) { clr_wdt();}// wait until packet is recved
packet_recving = 0; // reset it
plc_getframe(plc_frame);// read packet data
clr_wdt();
setup_t4(40, timeout_t4);delay_tx = 1; /*-延迟返回初始化-不可小于35*/
CRC = read_crc(); //取CRC的值
if (CRC == 0) { // check CRC21
Rxok = 0; clr_wdt();
t1_enable = 1;
adss_crc(plc_frame); //LED定时300ms
if(adss_ok==1){;//地址校验)//地址是否对
adss_ok = 0;
amr_send_frame(plc_frame); //数据发入串口
while(delay_tx)clr_wdt(); /*-延迟返回------*/
//Rx_Command_Reply(plc_frame[0]);//测试回复控制
//if(reply){
//Remote_Replies(plc_frame);//测试回复
clr_wdt();
//}
}}
if(CRC_switch){ //CRC开关
rx_return(0,plc_frame); //数据发入串口
clr_wdt(); /*-延迟返回------*/
}
setup_t2(4000, timeout_t2); //40S
}
if (timeout_40s)// Auto thres adjustment
{
thres_adjust();
packet_recved = 0; // reset it
}
if(~t1_enable)Rxok = 1;
clr_wdt();
plc_getframe(plc_frame);
clr_wdt();
}
}
/*=============================================================================*/
/*=============================================================================*/
// Process the received AMR message/cmd from meter
/*=============================================================================*/
void proc_amr_frame(uchar frame[])
{
uchar m_buf[2];
uchar contror_me;//B7B6 控制字
uchar command; //B5~B0 命令字
contror_me = (frame[AMR_OS_C] & 0xc0)>>6; //B7B6 控制字
command = frame[AMR_OS_C] & 0x3f; //B5~B0 命令字
switch (contror_me){
Rxok = 0;
case 0x00:{ uart_tx_mode(frame);}break;//发送到远方模块
case 0x01:{//本地设置控制
switch (command){
case 0x01:{if(frame[AMR_OS_L] == 0){m_buf[0] = Version1;m_buf[1] = Version2;return_inf(0x61,m_buf,2);}}break;//读版本号
case 0x02:{if(frame[AMR_OS_L] == 0){m_buf[0] = read_reg(REG_RD_F3);return_inf(0x62,m_buf,1);}}break;//读速率信息
case 0x03:{
if(frame[AMR_OS_L] == 1){
switch (frame[AMR_OS_L + 1] ){
case 0x01:{ w_flsh(0x01,0x04);}break; //设置速率2400bps
case 0x02:{ w_flsh(0x02,0x02);}break; //设置速率1200bps
case 0x04:{ w_flsh(0x04,0x01);}break; //设置速率 600bps
}
m_buf[0] = read_reg(REG_RD_F3);return_inf(0x62,m_buf,1);}}break;//读速率信息
case 0x04:{if(frame[AMR_OS_L] == 0)CRC_switch = 1;}break;//读设置接收数据CRC报出
case 0x05:{if(frame[AMR_OS_L] == 0)CRC_switch = 0;}break;//读设置接收数据CRC不报出
case 0x06:{;}break;
case 0x07:{;}break;
case 0x08:{if(frame[AMR_OS_L] == 0)sync_sendchar(0x7e);}break;
}
}break;
case 0x02:{ uart_tx_mode(frame);}break;//远程设置控制//发送到远方模块
case 0x03:{;}break;
}setup_t4(40, timeout_t4);delay_tx = 1;
}
/*=============================================================================*/
/* 数据发送到PC */
/*=============================================================================*/
void amr_send_frame(uchar ibuf[])
{
// idata uchar o_frame[26];
uchar i;
uchar En;
En = ibuf[AMR_OS_L] + 11; //串口返回
clr_wdt();
// preamble
for (i = 0; i < 5; i++) amr_frame[i] = mcu_pc[i]; //放入0xFE 68
clr_wdt();
for (i = 0; i < ibuf[AMR_OS_L]+6; i++)amr_frame[5+i] = ibuf[i]; //从C开始存放
amr_frame[En] = 0x16; //多补16h
uart_sendblock(amr_frame, En+1); //串口送至PC
clr_wdt();
}
/*=============================================================================* /
信息返回
/*=============================================================================*/
void return_inf(uchar frame,uchar inf_buf[],uchar dat)
{
uchar con;
uchar buf[18];
clr_wdt();
buf[0] = frame;
buf[1] = ADSS[0];
buf[2] = ADSS[1];
buf[3] = ADSS[2];
buf[4] = ADSS[3];
buf[AMR_OS_L] = dat;
for(con = 0;con < buf[AMR_OS_L];con ++)
buf[6+con] = inf_buf[con]; //放入状态信息
amr_send_frame(buf);//串口返回PC
}
/*=============================================================================* /
串口发到2200C
/*=============================================================================*/
void uart_tx_mode(uchar i_buf[])
{
uchar i,tom;
uchar no_all = 0;
uchar o_buf[18];
tom = i_buf[AMR_OS_L] + 6;
for (i = 0; i < tom; i++) //C, A,A,A,A,L, DATA
o_buf[i] = i_buf[i];//放入DATA数据
if(tom < 18){ //不够18个数据后补0
no_all = 18 - tom;
for (i = 0; i < no_all; i++)
o_buf[tom+i] = 0x00;
}
if(i_buf[AMR_OS_L] > 18)i_buf[AMR_OS_L] = 18;//超过18个数只认18个数
write_txbuffer(o_buf); //写入2200c
sync_sendchar(0x7e);
}
/*=============================================================================* /
接收数据重组
/*=============================================================================*/
void rx_return(bit y,uchar R_data[])
{
uchar i;
uchar o_buf[26];
if(y)
o_buf[0] = 0x40 + 0x04; //本地上传收到的CRC正确数据 B7B6 =bit-01,B5~B0 = 0x04h
else
o_buf[0] = 0x40 + 0x05; //本地上传收到的CRC错误数据 B7B6 =bit-01,B5~B0 = 0x05h
o_buf[1] = ADSS[0];
o_buf[2] = ADSS[1];
o_buf[3] = ADSS[2];
o_buf[4] = ADSS[3];
o_buf[AMR_OS_L] = 0x12; // L=18
for (i = 0; i < 18; i++)
o_buf[6 + i] = R_data[i];
amr_send_frame(o_buf);
}
/*=============================================================================*/
void adss_crc(uchar buf[])
{
if((buf[1] == ADSS[0])&&(buf[2] == ADSS[1])&&(buf[3] == ADSS[2])&&(buf[4] == ADSS[3]))
adss_ok = 1;
else adss_ok = 0;
}
/*=============================================================================*/
/*=============================================================================* /
/*=============================================================================*/
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$<<<<<软件说明>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/*=============================================================================* /
智能控制演示程序(根据UPLM2200 API协议设定)
软件说明:
1.更新的版本,支持电力线和PC通讯协议,
2.可读写FLASH作为地址掉电保存,写时通过串口发地址数据,掉电后地址在片内保存.
3.当写FLASH时,RXOK会闪动,之后返回一帧数据.表示已写入FLASH,
4.该程序设有看门狗,添加新组件时注意时间差.
5.如无接表时,可返回一帧仿真数据< *\ /* >
6.该串口的波特率为9600,偶校验, -
7.可通过PC或电力线上改变速率寄存器的值,并写入 FLASH ~
更新项目表:
------------------------------------------------------------------------------------------
|更新人 | 模块组件 | 更新时间 | 更新内容
--------------------------------------------------------------------------------------
| liangfq | 全部 | 2006-02-17 | 程序设计第一版
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
| liangfq | | |
| | | |
--------------------------------------------------------------------------------------
!!!!!!重复特别注意:写模块的地址必须从串口写入才有效!!!!!
!!!!!!重复特别注意:写模块的地址必须从串口写入才有效!!!!!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
!!!!!!重复特别注意:写模块的地址必须从串口写入才有效!!!!!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
!!!!!!重复特别注意:写模块的地址必须从串口写入才有效!!!!!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
!!!!!!重复特别注意:写模块的地址必须从串口写入才有效!!!!!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$<<<<<软件说明>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -