/************************************************
PLC通讯协议模拟程序
Modify by Alan, 2014/7/5
QQ:1762788595
版本1.0
*************************************************/
/************************************************
FX2N定义头文件
*************************************************/
#ifndef __FX2N_CPU_H__
#define __FX2N_CPU_H__
//声明PLC类型
#ifdef __FX2N_CPU_C__
#define FX2N_CPU_EXT
#else
#define FX2N_CPU_EXT extern
#endif
/*
FX2N 地址空间分配表
┌────────┬──────┬────────┬────────┬──────┬──────────────────────────────────┐
│ 软元件 │ 数量 │ 字节地址 │ 位地址 │ 字节数 │ 说明 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ M0-3071 │ 384 │ 0x0000-0x017F │ 0x0000-0x0BFF │ 3072 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ Y0-377 │ 32 │ 0x0180-0x019F │ 0x0C00-0x0CFF │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ 32 │ 0x01A0-0x01BF │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ M8000-8255 │ 32 │ 0x01C0-0x01DF │ 0x0E00-0x0EFF │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ C0-255 │ 32 │ 0x01E0-0x01FF │ 0x0F00-0x0FFF │ 256 │ 计数器超过设定值 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ T0-255 │ 32 │ 0x0200-0x021F │ 0x1000-0x10FF │ 256 │ 计时器超过设定值 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ 32 │ 0x0220-0x023F │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ X0-255 │ 32 │ 0x0240-0x025F │ 0x1200-0x12FF │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ 32 │ 0x0260-0x027F │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ S0-999 │ 125 │ 0x0280-0x02FC │ 0x1400-0x17E7 │ 1000 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ │ 0x02FD-0x02FF │ │ │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ MC0-3071 │ 384 │ 0x0300-0x037F │ │ 3072 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ YC0-377 │ 32 │ 0x0480-0x049F │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ 32 │ 0x04A0-0x04BF │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ │ 32 │ 0x04C0-0x04DF │ │ 256 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ CC0-255 │ 32 │ 0x04E0-0x04FF │ 0x2700-0x27FF │ 256 │ 计数器使能 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ TC0-255 │ 32 │ 0x0500-0x051F │ 0x2800-0x28FF │ 256 │ 计时器使能 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ │ 0x0520-0x06DF │ │ │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ CR0-255 │ 32 │ 0x06E0-0x06EF │ 0x3700-0x37FF │ 256 │ 计数器复位 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ TR0-255 │ 32 │ 0x0700-0x071F │ 0x3800-0x38FF │ 256 │ 计时器复位 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ │ 0x0720-0x09FF │ │ │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ CV0-199 │ 200 │ 0x0A00-0x0B8F │ │ 400 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ CV200-255 │ 56 │ 0x0B90-0x0C6F │ │ 112 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│CV200-255 32bit │ 56 │ 0x0C00-0x0CDF │ │ 112 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ NU │ │ 0x0CE0-0x0DFF │ │ │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D8000-8255 │ 256 │ 0x0E00-0x0FFF │ │ 512 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ TV0-255 │ 256 │ 0x1000-0x11FF │ │ 512 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ WW1 │ │ 0x1400-0x143F │ │ │ 批量监控时的元件地址 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ WR1 │ │ 0x1790-0x17CF │ │ │ 批量监控读出 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ WW2 │ │ 0x1440-0x---- │ │ │ 批量监控时的元件地址 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ WR2 │ │ 0x17D0-0x---- │ │ │ 批量监控读出 │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D0000-1023 │ 1024 │ 0x4000-0x47FF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D1024-2047 │ 1024 │ 0x4800-0x4FFF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D2048-3071 │ 1024 │ 0x5000-0x57FF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D3072-4095 │ 1024 │ 0x5800-0x5FFF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D4096-5119 │ 1024 │ 0x6000-0x67FF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D5120-6143 │ 1024 │ 0x6800-0x6FFF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D6144-7167 │ 1024 │ 0x7000-0x67FF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ D7168-8191 │ 1024 │ 0x7800-0x7FFF │ │ 2048 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ 参数 │ │ 0x8000-0x805B │ │ 92 │ │
├────────┼──────┼────────┼────────┼──────┼──────────────────────────────────┤
│ 程序 │ 8000 │ 0x805C-0xBEDB │ │ 16000 │ 8K步程序空间 │
└────────┴──────┴────────┴────────┴──────┴──────────────────────────────────┘
┌──────────┬─────────────────┐
│ 指令 │ 寻址空间 │
├──────────┼─────────────────┤
│"STX" "E00" 读内存 │ │
├──────────┤ │
│"STX" "E10" 读程序 │ 访问字节地址 │
├──────────┤ │
│"STX" "E01" 写内存 │ │
├──────────┤ │
│"STX" "E11" 写程序 │ │
├──────────┼─────────────────┤
│"STX" "E7" 强制On │ │
├──────────┤ 访问位地址 │
│"STX" "E7" 强制Off│ │
└──────────┴─────────────────┘
*/
//==========================================
#define ENQ 0x05 //请求
#define ACK 0x06 //PLC 接收正确响应
#define NACK 0x15 //PLC 接收错误响应
#define STX 0x02 //报文开始
#define ETX 0x03 //报文结束
#define EOT 0x04 //传送结束
// STX ,CMD ,ADDRESS, BYTES, ETX, SUM
// 02H, 30H, 31H,30H,46H,36H, 30H,34H, 03H, 37H,34H
// SUM=CMD+......+ETX
// 30h+31h+30h+46h+36h+30h+34h+03h=74h;
// 累加和超过两位取低两位
//定义PLC 文件内部变量,不充许外部访问
#ifdef __FX2N_CPU_C__
const char bcd_ascll[20]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,
0x37,0x38,0x39,0X41,0X42,0X43,0X44,0X45,0X46};
const char ascll_bcd[25]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0X0B,0X0C,0X0D,0X0E,0X0F};
const char ascll_h_bcd[25]={0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0XB0,0XC0,0XD0,0XE0,0XF0};
const char plc_type[2]={0XF6,0X5E};
const char plc_para[]={ //0x8000 0x40 byte
0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,
0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,
0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,
0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,
0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x30,
0x46,0x34,0x30,0x39,0x46,0x46,0x30,0x42,0x46,0x34,0x30,0x31,0x45,0x37,0x30,0x33,
0x36,0x34,0x30,0x45,0x43,0x37,0x30,0x45,0x44,0x43,0x30,0x45,0x46,0x46,0x30,0x45,
//0x8040 0x1c byte
0x39,0x30,0x30,0x31,0x46,0x45,0x30,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30};
const u16 special_d[256]={ // 1 0 3 2 5 4 7 6 9 8 b a d c f e //PLC初始化时将此数据初化到 memory[0x0E00]
0X00C8,0X5EF6,0X0002,0X0010,0X0000,0X0025,0X001E,0X0000, //0
0XFFFF,0X0000,0X0000,0X0000,0X0000,0X00A5,0X00A5,0X00A5, //1
0X00A5,0X00A5,0X0811,0X000F,0X000A,0X0000,0X0000,0X0000, //2
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X003D,0X001C, //3
0X0000,0X0000,0X0014,0X00FF,0X03D7,0X0000,0X0000,0X0000, //4
0XFFFF,0XFFFF,0XFFFF,0XFFFF,0XFFFF,0XFFFF,0XFFFF,0XFFFF, //5
0X0000,0XFFFF,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000, //6
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X183B,0X0000, //7
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X01F4,0X0000, //8
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000, //9
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000, //a
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000, //b
0X0000,0X0000,0X0000,0X0000,0X0064,0X5EF6,0X0008,0X0000, //c
0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000,0X0000, //d
0X0000,0X0000,0X0000,0X0000,0X0DDC,0X3DB6,0X0000,0X0000, //e
0X0000,0X0000,0X0000,0X0000,0X0002,0X0003,0X0000,0X0000};//f
//按照FX2N PLC内部空间表格划分 vvvvvvvvvvvv
u16 memory[0x11FF]; //M0 ~ TV255 内存空间
#define M_BASE 0x0000 //M0~M3071 基址
#define Y_BASE 0x0180 //Y0~Y377 基址
#define SP_M_BASE 0x01C0 //M8000~M8255 基址
#define C_OVER_BASE 0x01E0 //计数器超过设定标志
#define T_OVER_BASE 0x0200 //定时器超过设定标志
#define X_BASE 0x0240 //X输入
#define S_BASE 0x0280 //S步进
#define MC_BASE 0x0300 //MC
#define CC_BASE 0x04E0 //计数器使能
#define TC_BASE 0x0500 //定时器使能
#define CR_BASE 0x06E0 //计数器复位
#define TR_BASE 0x0700 //定时器复位
#define CV_BASE 0x0A00 //c0~c199计数器值
#define CV32_BASE 0x0C00 //c200~c255 计数器值
#define CV32_END 0x0CDF //c200~c255 计数器值结束
#define SP_D_BASE 0x0E00 //特殊寄存器
#define TV_BASE 0x1000 //定时器值
#define MEM_END_ADDRESS 0x11FF //内存结束地址
#define MAX_BIT_ADDRESS 0x4000 //最大的BIT地址
//非memory空间
#define BATCH_MONITOR_WW_S_BASE 0x1400 //批量监控表基址
#define BATCH_MONITOR_WW_E_BASE 0x149F //批量监控表结束
#define BATCH_MONITOR_WR_S_BASE 0x1790 //批量监控读出基址
#define BATCH_MONITOR_WR_E_BASE 0x17E0 //批量监控读出结束
#define MEM_D_S_BASE 0x4000 //d寄存器基址
#define PARA_S_BASE 0x8000 //参数基址
#define PARA_E_BASE 0x805B //参数结束
#define PROG_S_BASE 0x805C //程序基址
#define PROG_E_BASE 0x805C+16000 //程序结束
u16 ww[0xa0]; //批量监控寄存器地址指针
u16 wr[0x100]; //批量监控读出寄存器地址指针
#ifdef VECT_TAB_RAM
u16 mem_d[1000]; //如果在RAM中调试程序,因为RAM容量限制,寄存器只定义1000个
#define MEM_D_E_BASE 0x4000+1000 //d寄存器结束
#define PROG_IN_RAM_SIZE 4000 //如果在RAM中调试程序,因为RAM容量限制,将程序空间定义为2000步
u8 prog_area[PROG_IN_RAM_SIZE];
u8 * p_prog_area=&prog_area[0]; //程序空间基址
#else /* VECT_TAB_FLASH */
u16 mem_d[4000]; //如果在FLASH中运行程序,寄存器只定义4000个
#define MEM_D_E_BASE 0x4000+4000 //d寄存器结束
u8 * p_prog_area=0x8008000; //程序空间基址
#endif
u8 * p_memory=(u8 *)memory;
//按照FX2N PLC内部空间表格划分 ^^^^^^^^^^^^^
#endif //#ifdef __FX2N_CPU_C__
//位地址访问宏
#define BITADD(bit_addr) ( *( (volatile unsigned long *) ( 0x22000000 + ( ((u32)(&(p_memory[bit_addr/8])) ) -0x20000000) * 32 + (bit_addr%8)*4 ) ) )
FX2N_CPU_EXT void PLC_CPU_RUN(void);
FX2N_CPU_EXT void PLC_CPU_Init(void);
FX2N_CPU_EXT void ReceiveResponse(void);
FX2N_CPU_EXT u8 CheckSum(void);
FX2N_CPU_EXT void FromPLCReadData(void);
FX2N_CPU_EXT void StrToChar(u8 *src,u8 *dst);
FX2N_CPU_EXT void StrToInt(u8 *src,u16 *dst);
FX2N_CPU_EXT void ExtCommand(void);
FX2N_CPU_EXT void OutputACK(void);
FX2N_CPU_EXT void OutputNACK(void);
FX2N_CPU_EXT void ExRead(void);
FX2N_CPU_EXT void ReadAllData(void);
FX2N_CPU_EXT void WriteAllData(void);
FX2N_CPU_EXT void ExWrite(void);
#endif