无线简单网络协议WX-SNP
本帖最后由 sankong 于 2012-4-11 22:25 编辑;=====================================================================
; YT 无线终端设备通信规范:WXSNP Ver1.0
; 通信规范只有物理层DXspi,SNP层。本协议为对象之间的通信协议简化版!
; 网关外:传输层网络层:TCP/IP;会话层表示层:SNP;
; 应用层:动态网站服务器软件,用户端网络浏览器。
;=====================================================================
; 频带:90-2400 MHz;
; 普通轮询模式:240uA。1秒的轮询周期,轮询完255个终端约需3.5秒。
; 深度轮询模式:1uA。24小时的零点轮询周期,轮询完255个终端约需3.5秒。
; 通信速率:115.2KBPS。最大包64字节需4.4ms + CPU处理,晶振启动约1.1ms。所以信道时间为12ms。
; DXsnp对象与DXspi对象一起实现了无线模块间的通信,其实现代码量应少于0.3KB。
; 实现16个任务的调度对象DXdd,操作系统对象DXsys及DXsnp对象,DXspi对象作为单片机的最小核代码
; 量应小于0.5KB,通常低端单片机的FLASH只有2KB,SRAM只有128B。这样会有可在线升级的1.5KB用于
; 各种任务对象,如ADC,电压,电流,功率计算;PWM开关电源;温度、照度采集;百年实时时钟等。。
; 所以无线通信协议要简单实用。本人计划做带无线通信的智能LED路灯驱动电源:电源效率99%,功率
; 因数0.96。照度,2路温度,2路电压,电流,PWM控制及功率计算等。 无线芯片选用SI4432,单片机MSP430。
; 无线方面是新手,看资料阶段。双拼简写与英文习惯短语结合!
; 物理层帧:QD(4) + TB(2) + SNP帧 +CRC(2)
; 前导QD:4字节
; 同步字TB:2字节
; SNP帧
; 2字节 CRC
; 发送:SNP帧,最大发送64字节。
; 接收:SNP帧
; SNP帧结构:主从方式
; SNP8 + 目标设备的内存开始地址2字节KUD16 + 接收方节点地址字节JUD8 + 数据包长度字节L8+路由节点地址串LYD
; + 数据串UJ + 明匙2字节MU16
; SNP8 + KUD16 + JUD8 + L8 + LYD + UJ + MU16
; 安全性:最初发送方;用算法A加密发送数据串UJ,用与时间有关系的动态算法B计算出明匙MU16。
; 最终接收方:用与时间有关系的动态算法B对接收到的SNP8 + KUD16 + JUD8 + L8 + LYD + UJ计算出明匙MU16A,
; 如果MU16A不等于MU16,丢弃该帧,回应NAK。相等则用算法C解密数据串UJ,回应ACK或SNP_R。
; SNP字节:
;---------------------------------------------------------------------------------------------------------
; BIT7: 方向标志。1是下传,0是上传。
; BIT6--BIT4:
; 000 读数据DUJ.
; 001 写数据XUJ.
; 010 广播写数据GBXUJ. 主应用于网络节点同步修改共同参数或同步进入轮询模式或同步切换频道等。。。
; 011 段擦除DII。
; 100 广播段擦除GBDII。 应用于网络节点在线同步升级软件。
; 101 备用。
; 110 备用。
; 111 备用。
; BIT3--BIT0: 传播深度,最大16级,路由节点地址串LYD的长度。
; 分配节点地址,根据地理信息主节点扫描与同步下级节点,每一节点只有一个父节点,可有多个子节点。
; 主节点地址为0X00。每一节点有自己的路由级数(由扫描与同步自动确定),父节点的级数则要减一,子
; 节点的级数则加一。
;=================================================================================================
; 无线简单网络协议WX-SNP
; WX节点接收回应数据帧,出错丢弃该帧. 响应
; 读数据DUJ: 1000XXXX KUD16JUD8L8 LYD L1(L1<=32) MU16; SNP_R/NAK
; 写数据XUJ: 1001XXXX KUD16JUD8L8 LYD D1---DL1 MU16 ; ACK/NAK
; 广播写数据GBXUJ: 1010XXXX KUD16JUD8L8 LYD D1-DL1 MU16 ; ACK/NAK
; 擦洗一段DII: 1011XXXX KUD16JUD8L8 LYD 0X55AA MU16 ; ACK/NAK
; 广播擦洗一段GBDII:1100XXXX KUD16JUD8L8 LYD 0X55AA MU16 ; ACK/NAK
; 响应帧:
; ACK: 0XXXXXXX KUD16JUD8L8 LYD SR10X8080 ; SR1是本节点的16位状态寄存器值。
; NAK: 0XXXXXXX KUD16JUD8L8 LYD SR10X0000
; SNP_R: 0XXXXXXX KUD16JUD8L8 LYD SR1D1---DL1 MU16
;===========================================================================================
; SNP无线网络:由最多255个网关构成最多255*255个SNPZ子网。网关就是子网络、互联网的进出口。任一网关都可
; 按其网关地址来延时相应的秒数后在没网络时开始建立一个新的SNPZ子网络。Mesh网状拓扑。
; 设备:YT36路集线器。一个SNP网络可以有多于1600万个终端。
; 网关:可通过带PA的无线模块最大连接与管理255个集线器设备;网关的另一端通过WIFI,以太网等接入互联网。
; 集线器:可最大连接与管理255个无线传感器终端设备,构成SNPZ子网:YTD网络电表,YTU网络水表,YTM1读卡器。
; 之外还有传感器功能。集线器通过带PA的无线模块在绑定的网关对应的信道上与网关无线通信。
; 距离可达5KM。集线器还缓存预定要送到的终端上的数据包,直到终端唤醒,轮询数据。
; 在同一个小区的多个集线器处在不同的频点信道上。集线器可以是电池供电的轮询方式。
; 无线传感器终端: 只能在绑定的集线器对应的终端信道上以主从方式接收发送。
; 绑定方式: 同步及绑定上级节点,扫描及绑定下级节点。
; 路由方式: 在上下级节点间转发数据包。
; 轮询方式:轮询周期 T=1秒---3600秒。终端通常是电池供电,它不在收发时就处于睡眠以省电。
; 实时方式:不睡眠;实时收发。
; 工作时段:可设定无线网络每天只是工作在2个时间段。
; 在安全性方面,除了节点与终端内嵌的3种简单加解密算法(每个设备都有独立的128位密码)外,
;每一个设备加入网络必须申请,经网站管理员同意,并将设备ID号等备案才能得到节点地址,子网标识,
;频点信道,设备绑定等。
; 5。设置与绑定
; 网络标识WLBU16B:16字节的WLBU16B标识了所有的SNP无线网络。SNP.WLBU16B.15--SNP.WLBU16B.1标识
;了SNP网络的创建时间,位置,编号,等信息。SNP.WLBU16B.1-0为子网标识,一个SNP网络可以有最多255个网
;关构成最多255*255个子网。0XFF为广播。SNP无线网络有一个IP6的IP地址,网络的查询与管理是在互联网上进行。
; 所有设备出厂时都有1个地球唯一的16字节的ID标识,设备的设置与(解)绑定都是通过互联网上的
; 管理员相关网页进行的。任一设备都有一个FLASH设备配置信息区,删除一个设备就是擦除该信息区。
; 创建SNP网络的网页:根据网关的ID为SNP网络的各个网关设置网络标识WLBU16B,所属子网,网关参数
; (TCP/IP)。发信令帧,初始化(分配信道,设置密码)与启动网关协调器。
; 构建SNPZ子网的网页:根据地理位置信息,设备的ID加入, 分配的节点地址,信道时隙,信道绑定。
; 设置集线器节点的网页:根据地理位置信息,设备的ID加入多个集线器节点。分配节点地址。
; 绑定终端设备的网页:根据设备的ID,分配终端设备的节点地址,根据地理位置信息绑定到相应的集线器。
; 一个集线器可绑定最大255个无线传感器终端设备。
; 本协议不支持个体跳频,可整个子网跳频到另一固定的频道上,以避开干扰频道。不支持移动节点定位。
; 举例:一个SNPZ子网有节点地址为1---15的15个无线终端相互距离2KM排成一条直线,无线终端的有效通信
; 距离为2KM。还无绑定的终端都是处于实时方式。0X00的集线器(由配置信息知只有15个终端):
; 1。对15个终端进行轮发读,只找到了最近的6号终端,接着写6号终端配置信息,完成6号终端绑定。
; 2。通过6号终端“路由”对14个终端进行轮发读,只找到了与其最近的3号终端有ACK反映,接着写3号终端配置信息,
; 完成3号终端绑定。3号终端将同步于6号终端并以6号终端为父节点而不是集线器,相对于集线器的同步有一个延迟。
;。。。。。。。。。。。。。。。。。。
; 15。最终完成了最后一个终端1号的绑定。
; 这样集线器到1号,虽相距了30KM。但通过中间的15个节点做路由中继,照样可以收发成功通信。
; 集线器就是这样建立了路由表。为了简化代码,费脑筋啊。
;===========================================================================================
; 对象DX。程序类的对象一般有属性赋值,初始化方法,接口。为了简化代码量,我将所有的程序类对象的
; 初始化宏都放在了统一的一个sys_init方法里;方法即函数即子程序。面向对象编程的目的之一就是为了简明,
; 清晰,条理。接口就是指一组事件(消息)驱动的方法入口表。最简单的接口就是中断入口表,只不过中
; 断事件(消息)驱动是由硬件实现的。如果对某个中断编制成中断类对象,那么这个中断类对象的入口就
; 在中断接口里。对象必须有一个入口方法,也称对象运动的接口方法。应用类的对象运动的接口方法,高
; 级的就在系统对象DXsys的另一个接口-调度接口里,低级的就在某对象的接口指向的某对象的接口指向的。。。
; 接口里。复杂点的调度接口可独立成一个调度对象DXdd,而DXsys就不用调度接口,而是由中断类DXt20m进入。
; 一般的操作系统的256任务优先抢占式调读算法其实:
; BC256TSS ; BC指位容器,BC256即是定义任务变量TSS为256位变量。
; (BC32 JKB + BC8 XV(1,TSS))->PC; 在TSS从最高位往低位寻找第一个为1的序数 + 接口表初地址后的形成
; 的指针的内容送PC,即实现了当时最高优先级的任务。这还是不行的,如果一个任务死循环那系统就崩了。
; 所以还需一个20ms的中断类定时器对象DXt20ms来配合。即是一个高优先级任务运行20ms后,除非有新的消息
; 激发,否则只能到后面排队。DXt20ms会进行任务切换等。通常任务可能有要实时处理的部分,也有慢速的部
; 分。象我们的无线通信模块,DXsnp对象就是相对慢速的普通任务对象,而DXspi对象则是实时中断类对象。
; 因为不止一种中断,所以中断类的对象代码应尽可能短而快;尽可能将长而慢的代码放到任务类对象里。
; 操作系统这概念应取消,会影响到机器智能化的进程。生命是由许多功能部件交互运动的整体表现。
; 面向对象编程将是机器智能化的实现手段。很遗憾,现在的单片机没有这条指令:在TSS从最高位往低位寻找
; 第一个为1的序数。需用好几条指令来实现。这是一条非常有用的指令!
; 编写对象的代码工作通常是编写事件处理方法。由事件驱动接口跳转到各个事件处理。
; 事件驱动模式通常有事件消息驱动模式(如任务调度)与状态机事件驱动模式(如DXsnp对象的。。)。
;============================================================================================= 关注,有没有实现跳频等抗干扰
。 是不是广告贴啊 谢谢!期待更多佳作 关注 MARK 本帖最后由 sankong 于 2012-4-12 21:39 编辑
;=========================================================================================================
; 无线简单网络协议WX-SNP:主从通信模式。
; 请求帧:
; 读数据DUJ: 1000XXXX KUD16JUD8L8 LYD L1(L1<=32) MU16; SNP_R/NAK
; 写数据XUJ: 1001XXXX KUD16JUD8L8 LYD D1---DL1 MU16; ACK/NAK
; 广播写数据GBXUJ: 1010XXXX KUD16JUD8L8 LYD D1-DL1 MU16; ACK/NAK
; 擦洗一段DII: 1011XXXX KUD16JUD8L8 LYD 0X55AA MU16; ACK/NAK
; 广播擦洗一段GBDII:1100XXXX KUD16JUD8L8 LYD 0X55AA MU16; ACK/NAK
; 响应帧:
; ACK: 0XXXXXXX SR1JUD8L8 LYD 0X8080 ; SR1是响应节点的16位状态寄存器值。
; NAK: 0XXXXXXX SR1JUD8L8 LYD 0X0000
; SNP_R: 0XXXXXXX SR1JUD8L8 LYD L1(L1<=32)D1---DL1MU16
;========================================================================================================
//DXsnp说明:任务类对象。
//处理snp协议.
//使用系统对象DXsys的调度接口里的 TSS_snp 函数作为DXsnp对象运动的入口函数.
//互动对象:DXspi,DXsi4432irq,DXclock,DXtime1。由同步实时时钟DXclock对象初始化si4432为接收数
//据包中断状态。由DXsi4432irq对象判断接收包无错则触发DXsnp运行,并做发射后的善后处理。DXtime1定
//时器1对象监控si4432收发模式是否超时。DXsnp对象处理SNP协议后自行停止。
//
//MSP430 LK Library(类库) v1.0
//
//sankong
//YT, Inc.
//4/2012
//IAR Embedded Workbench v5.1
//----------------------------------------------------------------------------
//属性说明:MSP430FXXXX.hUSI
// acom.h
//#define PT2 R14 ; PT2作为发数据的指针。定义为寄存器变量可减少代码段,加快运行速度。
//#define PT1 R13 ; PT1作为收数据的指针。
//#define IDL R12L; 数据的长度变量。
//#define SR2 R12H; 通信状态寄存器。
//#define TSS R4 ; 16个任务的任务标志寄存器。
//#define SR1 R5 ; 系统状态寄存器。
//#define A R6 ; 任务使用的通用寄存器A.
//#define B R6 ; 任务使用的通用寄存器B.
//SNP8 EQU 0x026A ; snp字节
//KUD16H EQU 0x0269 ; 目标设备的内存开始地址高字节
//KUD16L EQU 0x0268 ; 目标设备的内存开始地址低字节
//JUD8 EQU 0x0267 ; 接收方节点地址字节
//L8 EQU 0x0266 ; 数据包长度字节,最大49字节。
//LYD EQU 0x0265 ; 路由节点地址串,最大占15字节。
//UJ ; 数据串,最大占32字节。
//MU16 ; 明匙2字节。
//#define TRANSMIT_HEADER_3 0x3A00// 发射帧头3
//#define RECEIVED_HEADER_3 0x4700// 接收帧头3
//数据FLASH区分配:
//#define BJDJ8 0x1000 ; 本节点级数。
//#define FJD8 0x1001 ; 父节点地址。
//#define BJD8 0x1002 ; 本节点地址。
//#define ZJD8 0x1010 ; 子节点地址串。0X1010----0X106F,最多可绑定96个子节点。
//SR2 通信状态寄存器
//SPI_WI equ 0x0400 ; SPI通信完成标志.
//WX_WR equ 0x0200 ; WX Read/Write Mode标志.
//WX_BWR equ 0x0100 ; WX(无线) Burst Read/Write Mode标志.
//----------------------------------------------------------------------------
//DXsnp对象运动的入口函数说明:
//使用 TSS_snp 函数作为DXsnp对象运动的入口函数。
//通过SPI口读写数据包的事情主要由DXspi对象完成。
//DXsnp的状态机事件驱动接口说明:
//由事件驱动接口跳转到各个事件处理,
//事件驱动模式通常有事件消息驱动模式与状态机事件驱动模式。
//----------------------------------------------------------------------------
TSS_snp:
bic #TSS_snp_BV,TSS; 清任务标志.
mov #SNP8,PT1 ; PT1指向接收数据包初始地址。
call #SPI_Burst_READ; 突发读取整个数据包。最终PT1指向MU16L
bit.b #BIT7,&SNP8 ; 测试 SNP8最高位.
jnz snp_xi ; 为1跳 下传事件驱动.
snp_fu:
mov.b &FJD8,&JUD8 ; 修改接收方节点地址为父节点地址。
snp_fu1:
call #SPI_WRITE_HEADER; 置发射模式并写发射帧头及数据包长度。
call #SPI_Burst_WRITE ; 突发写整个数据包。路由上传。发射完后睡眠等事情由
ret ; DXsi4432irq对象去做。
snp_xi:
mov.b &SNP8,A
and.b #0x0F,A ; 得到路由深度
cmp.b &BJDJ8,A ; 本节点级数与路由深度比较,
JLO snp_NAK ; 小于跳发NAK
jnz snp_XLY ; 不为0,跳下传路由。
call #snp_BSF ; 本节点地址是最终地址,用算法B对接收到的数据包计算出明匙MU16A->A。
cmp @PT1,A ; MU16A等于 MU16?
jnz snp_NAK ; 不等,跳发NAK
call #snp_CSF ; 相等则用算法C解密数据串UJ。
DXsnp_ujqd: ; 事件驱动接口
mov.b &SNP8,A
and.b #0x70,A
rra.b A
rra.b A
rra.b A
rra.b A
mov.b DXsnp_ujqdB(A),A
add A,PC
DXsnp_ujqdB: ; 事件驱动表入口
DB DXsnp_DUJ ; 读数据DUJ事件处理函数入口.
DB DXsnp_XUJ ; 写数据XUJ事件处理函数入口.
DB DXsnp_GBXUJ ; 广播写数据XUJ事件处理函数入口.
DB DXsnp_DII ; 段擦除DII事件处理函数入口.
DB DXsnp_GBDII ; 广播段擦除GBDII事件处理函数入口.
DB RET ; 备用.
DB RET ; 备用.
DB RET ; 备用.
snp_NAK:
mov SR1,&KUD16L ; 修改KUD16,SR1内容需上传。
mov #LYD,PT1 ; PT1->LYD串的后面地址。
sub A,PT1
clr 0(PT1) ; NAK
incd A
mov.b A,&L8 ; 修改数据包长度,
jmp snp_fu
snp_XLY:
mov #LYD-1,PT1 ; PT1->下级节点地址。
sub &BJDJ8,PT1
mov.b @PT1,A
mov #ZJD8-1,PT1 ; PT1->子节点地址串表。
snp_XLY1:
inc PT1
cmp #0x1070,PT1
jz snp_NAK ; 没有绑定的子节点地址跳发NAK。
cmp.b @PT1,A ; 路由节点地址串的下一级节点地址在本节点绑定子节点地址里?
jnz snp_XLY1
mov.b A,&JUD8 ; 找到,修改接收方节点地址为下一级节点地址。
jmp snp_fu1 ; 跳,下传路由。
顶,正合我意,学习,小巧玲珑。 6楼有错,又没法再编辑! 只好再发修改贴。
;============================================================================================
; 无线简单网络协议WX-SNP:主从通信模式。
; 请求帧:
; 读数据DUJ: 1000XXXX KUD16JUD8L8 LYD L1(L1<=32) MU16; SNP_R/NAK
; 写数据XUJ: 1001XXXX KUD16JUD8L8 LYD D1---DL1 MU16; ACK/NAK
; 擦洗一段DII: 1010XXXX KUD16JUD8L8 LYD 0X55AA MU16; ACK/NAK
; 备用: 1011XXXX
; 广播备用: 1100XXXX
; 广播写数据GBXUJ: 1101XXXX KUD16JUD8L8 LYD D1-DL1 MU16; ACK/NAK
; 广播擦洗一段GBDII: 1110XXXX KUD16JUD8L8 LYD 0X55AA MU16; ACK/NAK
; 广播备用: 1111XXXX
; 响应帧:
; ACK: 0XXXXXXX SR1JUD8L8 LYD 0X8080 ; SR1是响应节点的16位状态寄存器值。
; NAK: 0XXXXXXX SR1JUD8L8 LYD 0X0000
; SNP_R: 0XXXXXXX SR1JUD8L8 LYD L1(L1<=32)D1---DL1MU16
; BIT7: 方向标志。1是下传,0是上传。BIT6: 广播标志;1是广播命令。
;========================================================================================================
//DXsnp说明:任务类对象。
//处理snp协议.
//使用系统对象DXsys的调度接口里的 TSS_snp 函数作为DXsnp对象运动的入口函数.
//互动对象:DXspi,DXsi4432irq,DXclock,DXtime1。由同步实时时钟DXclock对象初始化si4432为接收数
//据包中断状态。由DXsi4432irq对象判断接收包无错则触发DXsnp运行,并做发射后的善后处理。DXtime1定
//时器1对象监控si4432收发模式是否超时。DXsnp对象处理SNP协议后自行停止。
//
//MSP430 LK Library(类库) v1.0
//
//sankong
//YT, Inc.
//4/2012
//IAR Embedded Workbench v5.1
//----------------------------------------------------------------------------
//属性说明:MSP430FXXXX.hUSI
// acom.h
//#define PT2 R14 ; PT2作为发数据的指针。定义为寄存器变量可减少代码段,加快运行速度。
//#define PT1 R13 ; PT1作为收数据的指针。
//#define IDL R12L; 数据的长度变量。
//#define SR2 R12H; 通信状态寄存器。
//#define TSS R4 ; 16个任务的任务标志寄存器。
//#define SR1 R5 ; 系统状态寄存器。
//#define A R6 ; 任务使用的通用寄存器A.
//#define B R6 ; 任务使用的通用寄存器B.
//SNP8 EQU 0x026A ; snp字节
//KUD16H EQU 0x0269 ; 目标设备的内存开始地址高字节
//KUD16L EQU 0x0268 ; 目标设备的内存开始地址低字节
//JUD8 EQU 0x0267 ; 接收方节点地址字节
//L8 EQU 0x0266 ; 数据包长度字节,最大49字节。
//LYD EQU 0x0265 ; 路由节点地址串,最大占15字节。
//UJ ; 数据串,最大占32字节。
//MU16 ; 明匙2字节。
//#define TRANSMIT_HEADER_3 0x3A00// 发射帧头3
//#define RECEIVED_HEADER_3 0x4700// 接收帧头3
//数据FLASH区分配:
//#define BJDJ8 0x1000 ; 本节点级数。
//#define FJD8 0x1001 ; 父节点地址。
//#define BJD8 0x1002 ; 本节点地址。
//#define ZJD8 0x1010 ; 子节点地址串。0X1010----0X106F,最多可绑定96个子节点。
//SR2 通信状态寄存器
//SPI_WI equ 0x0400 ; SPI通信完成标志.
//WX_WR equ 0x0200 ; WX Read/Write Mode标志.
//WX_BWR equ 0x0100 ; WX(无线) Burst Read/Write Mode标志.
//----------------------------------------------------------------------------
//DXsnp对象运动的入口函数说明:
//使用 TSS_snp 函数作为DXsnp对象运动的入口函数。
//通过SPI口读写数据包的事情主要由DXspi对象完成。
//DXsnp的状态机事件驱动接口说明:
//由事件驱动接口跳转到各个事件处理,
//事件驱动模式通常有事件消息驱动模式与状态机事件驱动模式。
//----------------------------------------------------------------------------
TSS_snp:
bic #TSS_snp_BV,TSS; 清任务标志.
mov #SNP8,PT1 ; PT1指向接收数据包初始地址。
call #SPI_Burst_READ; 突发读取整个数据包。最终PT1指向MU16L
bit.b #BIT7,&SNP8 ; 测试 SNP8最高位.
jnz snp_xi ; 为1跳 下传事件驱动.
snp_fu:
mov.b &FJD8,&JUD8 ; 修改接收方节点地址为父节点地址。
snp_fu1:
call #SPI_WRITE_HEADER; 置发射模式并写发射帧头及数据包长度。
call #SPI_Burst_WRITE ; 突发写整个数据包。路由上传。发射完后睡眠等事情由
ret ; DXsi4432irq对象去做。
snp_xi:
bit.b #BIT7,&SNP8 ; 测试 SNP8的BIT6位.
jnz snp_xi1 ; 为1跳 广播事件驱动.
mov.b &SNP8,A
and.b #0x0F,A ; 得到路由深度.
cmp.b &BJDJ8,A ; 本节点级数与路由深度比较,
JLO snp_NAK ; 小于跳发NAK
jnz snp_XLY ; 不为0,跳下传路由。
snp_xi1:
call #snp_BSF ; 本节点地址是最终地址,用算法B对接收到的数据包计算出明匙MU16A->A。
cmp @PT1,A ; MU16A等于 MU16?
jnz snp_NAK ; 不等,跳发NAK
call #snp_CSF ; 相等则用算法C解密数据串UJ。
DXsnp_ujqd: ; 事件驱动接口
mov.b &SNP8,A
and.b #0x70,A
rra.b A
rra.b A
rra.b A
rra.b A
mov.b DXsnp_ujqdB(A),A
add A,PC
DXsnp_ujqdB: ; 事件驱动表入口
DB DXsnp_DUJ ; 读数据DUJ事件处理函数入口.
DB DXsnp_XUJ ; 写数据XUJ事件处理函数入口.
DB DXsnp_DII ; 段擦除DII事件处理函数入口.
DB RET ; 备用.
DB RET ; 备用.
DB DXsnp_XUJ ; 广播写数据XUJ事件处理函数入口.
DB DXsnp_DII ; 广播段擦除GBDII事件处理函数入口.
DB RET ; 备用.
snp_NAK:
clr B ; NAK
snp_AK:
mov SR1,&KUD16L ; 修改KUD16,SR1内容需上传。
mov #LYD,PT1 ; PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A ; 得到路由深度.
sub A,PT1
mov B,0(PT1)
incd A
mov.b A,&L8 ; 修改数据包长度,
jmp snp_fu
snp_ACK:
mov #0X8080,B ; ACK
jmp snp_AK
snp_XLY:
mov #LYD-1,PT1 ; PT1->下级节点地址。
sub &BJDJ8,PT1
mov.b @PT1,A
mov #ZJD8-1,PT1 ; PT1->子节点地址串表。
snp_XLY1:
inc PT1
cmp #0x1070,PT1
jz snp_NAK ; 没有绑定的子节点地址跳发NAK。
cmp.b @PT1,A ; 路由节点地址串的下一级节点地址在本节点绑定子节点地址里?
jnz snp_XLY1
mov.b A,&JUD8 ; 找到,修改接收方节点地址为下一级节点地址。
jmp snp_fu1 ; 跳,下传路由。
DXsnp_DUJ: ; 读数据DUJ事件处理函数入口.
mov #LYD,PT1 ; PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A ; 得到路由深度.
sub A,PT1
mov.b @PT1+,B ; L1->B
mov #KUD16L,PT2 ; PT2->目标设备的内存开始地址。
DXsnp_DUJ1:
mov.b @PT2+,0(PT1) ; 读内存到发送区.
inc PT1
dec B
jnz DXsnp_DUJ1
jmp snp_fu
DXsnp_DII: ; 段擦除DII事件处理函数入口.
CMP #0X55AA,-2(PT1); 是段察除?
JNZ snp_NAK
mov #KUD16L,PT2 ; PT2->目标设备的内存开始地址。
CMP #0X1000,PT2 ; 0X1000后才是FLASH
JLO snp_NAK
CMP #0FC00H,PT2 ; 最后的1KB是核心区,禁止察除。
JHS snp_NAK
CALL #DXflash_RASE ; 擦洗一段.
JMP snp_ACK
DXsnp_XUJ: ; 写数据XUJ事件处理函数入口.
mov #LYD,PT1 ; PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A ; 得到路由深度.
sub A,PT1
mov.b &L8,B ; L8->B
sub.b A,B ; 得到数据包长度->B
mov #KUD16L,PT2 ; PT2->目标设备的内存开始地址。
CMP #0X0200,PT2 ; 0X0200后才是RAM
JLO snp_NAK
CMP #01000H,PT2 ; 0X1000后是FLASH
JHS WSFLASH ; 写数据段A,B或程序FLASH
WRAM:
MOV.B @PT1+,0(PT2)
INC PT2
DEC.B B
JNZ WRAM
jmp snp_ACK
WFLASH:
CMP #0FC00H,PT2 ; 最后的1KB是核心区,禁止写。
JHS snp_NAK
RRA B ; 写FLASH需一次写一个字。
DINT
CALL #DXflash_FLASH
JMP snp_ACK
{:funk:}还是汇编的哦。。。 有文档不? 代码没经实际测试!仅供参考,我的电路板还没出来。
//*******************************************************************************
// MSP430F20x3 PWM_LED
//----------------------------------------------------------------------------------
#include"msp430x20x3.h"
#include"acom.h"
//-------------------------------------------------------------------------------
//DXsys 系统对象
ORG 0F800h // Program Reset
//-------------------------------------------------------------------------------
RESET mov.w #0280h,SP // Initialize stackpointer
CALL #DXsys_init // 各种对象初始化。
Mainloop
// MOV #WDT_ARST_1000,&WDTCTL // Define watchdog,重启动WDT,1S
CALL #SYS_DD // 优先级任务调度。
// bis.w #LPM3+GIE,SR // Enter LPM3, enable interrupts
jmp Mainloop // 2t,Repeat for next cycle
SYS_DD: // 优先级任务处理接口. BITF,BIT7--BIT0 有9个任务备用。
BIT #BITE,TSS
JNZ TSS_snp // DXsnp对象入口。
BIT #BITD,TSS
JNZ MLRET // 任务屏蔽.
BIT #BITC,TSS
JNZ TSS_sd16_LAC // DXsd16_LAC电压采集周期任务。
BIT #BITB,TSS
JNZ TSS_sd16_AC // DXsd16_AC电压采集周期任务。
BIT #BITA,TSS
JNZ TSS_sd16_A // DXsd16_A电流采集周期任务。
BIT #BIT9,TSS
JNZ TSS_sd16_ICT // DXsd16_ICTIC温度采集任务。
BIT #BIT8,TSS
JNZ TSS_pwm_DY // pwm LED电源控制任务。
MLRET:
RET
#include"DXwxsnp.inc"
#include"DXspi.inc"
#include"DXclock.inc"
#include"DXflash.inc"
#include"DXsys_init.inc"
#include"irqt.inc" //#include "DXsi4432irq.inc"// #include "DXtime1.inc"// #include "DXpwm_DY.inc"
//-------------------------------------------------------------------------------
// MSP430 RESET Vector 中断入口表:
//-------------------------------------------------------------------------------
ORG 0FFFEh
DW RESET //
ORG WDT_VECTOR
DW WDT_ISR // 用WDT定时器作1s时钟中断,
ORG TIMERA0_VECTOR
DW TA0_ISR //
ORG TIMERA1_VECTOR
DW TA1_ISR //
ORG SD16_VECTOR //
DW SD16_ISR //
ORG USI_VECTOR
DW USI_ISR //
ORG PORT1_VECTOR
DW P1_ISR //
END
改过的,不是最终稿!可过编译。
//=========================================================================================================
// 无线简单网络协议WX-SNP:主从通信模式。
// 请求帧:
// 读数据DUJ: 1000XXXX KUD16JUD8L8 LYD L1(L1<=32) MU16// SNP_R/NAK
// 写数据XUJ: 1001XXXX KUD16JUD8L8 LYD D1---DL1 MU16// ACK/NAK
// 擦洗一段DII: 1010XXXX KUD16JUD8L8 LYD 0X55AA MU16// ACK/NAK
// 备用: 1011XXXX
// 广播备用: 1100XXXX
// 广播写数据GBXUJ: 1101XXXX KUD16JUD8L8 LYD D1-DL1 MU16// ACK/NAK
// 广播擦洗一段GBDII: 1110XXXX KUD16JUD8L8 LYD 0X55AA MU16// ACK/NAK
// 广播备用: 1111XXXX
// 响应帧:
// ACK: 0XXXXXXX SR1JUD8L8 LYD 0X8080 // SR1是响应节点的16位状态寄存器值。
// NAK: 0XXXXXXX SR1JUD8L8 LYD 0X0000
// SNP_R: 0XXXXXXX SR1JUD8L8 LYD L1(L1<=32)D1---DL1MU16
// BIT7: 方向标志。1是下传,0是上传。BIT6: 广播标志;1是广播命令。
//========================================================================================================
//DXsnp说明:任务类对象。
//处理snp协议.
//使用系统对象DXsys的调度接口里的 TSS_snp 函数作为DXsnp对象运动的入口函数.
//互动对象:DXspi,DXsi4432irq,DXclock,DXtime1。由同步实时时钟DXclock对象初始化si4432为接收数
//据包中断状态。由DXsi4432irq对象判断接收包无错则触发DXsnp运行,并做发射后的善后处理。DXtime1定
//时器1对象监控si4432收发模式是否超时。DXsnp对象处理SNP协议后自行停止。
//
//MSP430 LK Library(类库) v1.0
//
//sankong
//YT, Inc.
//4/2012
//IAR Embedded Workbench v5.1
//----------------------------------------------------------------------------
//属性说明:MSP430FXXXX.hUSI
// acom.h
//#define PT2 R14 // PT2作为发数据的指针。定义为寄存器变量可减少代码段,加快运行速度。
//#define PT1 R13 // PT1作为收数据的指针。
//; #define IDL R12L// 数据的长度变量。
//; #define SR2 R12H// 通信状态寄存器。
//#define TSS R4 // 16个任务的任务标志寄存器。
//#define SR1 R5 // 系统状态寄存器。
//#define A R6 // 任务使用的通用寄存器A.
//#define B R7 // 任务使用的通用寄存器B.
//SNP8 EQU 0x026A // snp字节
//KUD16H EQU 0x0269 // 目标设备的内存开始地址高字节
//KUD16L EQU 0x0268 // 目标设备的内存开始地址低字节
//JUD8 EQU 0x0267 // 接收方节点地址字节
//L8 EQU 0x0266 // 数据包长度字节,最大49字节。
//LYD EQU 0x0265 // 路由节点地址串,最大占15字节。
//UJ // 数据串,最大占32字节。
//MU16 // 明匙2字节。
//#define TRANSMIT_HEADER_30x3A00 // 发射帧头3
//#define RECEIVED_HEADER_30x4700 // 接收帧头3
//数据FLASH区分配:
//#define BJDJ8 0x1000 // 本节点级数。
//#define FJD8 0x1001 // 父节点地址。
//#define BJD8 0x1002 // 本节点地址。
//#define ZJD8 0x1010 // 子节点地址串。0X1010----0X106F,最多可绑定96个子节点。
//SR2 通信状态寄存器
//SPI_WI equ 0x0400 // SPI通信完成标志.
//WX_WR equ 0x0200 // WX Read/Write Mode标志.
//WX_BWR equ 0x0100 // WX(无线) Burst Read/Write Mode标志.
//----------------------------------------------------------------------------
//DXsnp对象运动的入口函数说明:
//使用 TSS_snp 函数作为DXsnp对象运动的入口函数。
//通过SPI口读写数据包的事情主要由DXspi对象完成。
//DXsnp的状态机事件驱动接口说明:
//由事件驱动接口跳转到各个事件处理,
//事件驱动模式通常有事件消息驱动模式与状态机事件驱动模式。
//----------------------------------------------------------------------------
TSS_snp:
bic #TSS_snp_BV,TSS// 清任务标志.
mov #SNP8,PT1 // PT1指向接收数据包初始地址。
call #SPI_Burst_READ// 突发读取整个数据包。最终PT1指向MU16L
bit.b #BIT7,&SNP8 // 测试 SNP8最高位.
jnz snp_xi // 为1跳 下传事件驱动.
snp_fu:
mov.b &FJD8,&JUD8 // 修改接收方节点地址为父节点地址。
snp_fu1:
call #SPI_WRITE_HEADER// 置发射模式并写发射帧头及数据包长度。
call #SPI_Burst_WRITE // 突发写整个数据包。路由上传。发射完后睡眠等事情由
ret // DXsi4432irq对象去做。
snp_xi:
bit.b #BIT7,&SNP8 // 测试 SNP8的BIT6位.
jnz snp_xi1 // 为1跳 广播事件驱动.
mov.b &SNP8,A
and.b #0x0F,A // 得到路由深度.
cmp.b &BJDJ8,A // 本节点级数与路由深度比较,
JLO snp_NAK // 小于跳发NAK
jnz snp_XLY // 不为0,跳下传路由。
snp_xi1:
call #snp_BSF // 本节点地址是最终地址,用算法B对接收到的数据包计算出明匙MU16A->A。
cmp @PT1,A // MU16A等于 MU16?
jnz snp_NAK // 不等,跳发NAK
call #snp_CSF // 相等则用算法C解密数据串UJ。
DXsnp_ujqd: // 事件驱动接口
mov.b &SNP8,A
and.b #0x70,A
rra.b A
rra.b A
rra.b A
rra.b A
mov.b DXsnp_ujqdB(A),A
add A,PC
DXsnp_ujqdB: // 事件驱动表入口
DB DXsnp_DUJ // 读数据DUJ事件处理函数入口.
DB DXsnp_XUJ // 写数据XUJ事件处理函数入口.
DB DXsnp_DII // 段擦除DII事件处理函数入口.
DB BRET // 备用.
DB BRET // 备用.
DB DXsnp_XUJ // 广播写数据XUJ事件处理函数入口.
DB DXsnp_DII // 广播段擦除GBDII事件处理函数入口.
DB BRET // 备用.
snp_NAK:
clr B // NAK
snp_AK:
mov SR1,&KUD16L // 修改KUD16,SR1内容需上传。
mov #LYD,PT1 // PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A // 得到路由深度.
sub A,PT1
mov B,0(PT1)
incd A
mov.b A,&L8 // 修改数据包长度,
jmp snp_fu
snp_ACK:
mov #0X8080,B // ACK
jmp snp_AK
snp_XLY:
mov #LYD-1,PT1 // PT1->下级节点地址。
sub &BJDJ8,PT1
mov.b @PT1,A
mov #ZJD8-1,PT1 // PT1->子节点地址串表。
snp_XLY1:
inc PT1
cmp #0x1070,PT1
jz snp_NAK // 没有绑定的子节点地址跳发NAK。
cmp.b @PT1,A // 路由节点地址串的下一级节点地址在本节点绑定子节点地址里?
jnz snp_XLY1
mov.b A,&JUD8 // 找到,修改接收方节点地址为下一级节点地址。
jmp snp_fu1 // 跳,下传路由。
DXsnp_DUJ: // 读数据DUJ事件处理函数入口.
mov #LYD,PT1 // PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A // 得到路由深度.
sub A,PT1
mov.b @PT1+,B // L1->B
mov #KUD16L,PT2 // PT2->目标设备的内存开始地址。
DXsnp_DUJ1:
mov.b @PT2+,0(PT1) // 读内存到发送区.
inc PT1
dec B
jnz DXsnp_DUJ1
call #snp_ASF // 用算法A加密数据串UJ。
jmp snp_fu
DXsnp_DII: // 段擦除DII事件处理函数入口.
CMP #0X55AA,-2(PT1)// 是段察除?
JNZ snp_NAK
mov #KUD16L,PT2 // PT2->目标设备的内存开始地址。
CMP #0X1000,PT2 // 0X1000后才是FLASH
JLO snp_NAK
CMP #0FC00H,PT2 // 最后的1KB是核心区,禁止察除。
JHS snp_NAK
CALL #DXflash_RASE // 擦洗一段.
JMP snp_ACK
DXsnp_XUJ: // 写数据XUJ事件处理函数入口.
mov #LYD,PT1 // PT1->LYD串的后面地址。
mov.b &SNP8,A
and.b #0x0F,A // 得到路由深度.
sub A,PT1
mov.b &L8,B // L8->B
sub.b A,B // 得到数据包长度->B
mov #KUD16L,PT2 // PT2->目标设备的内存开始地址。
CMP #0X0200,PT2 // 0X0200后才是RAM
JLO snp_NAK
CMP #01000H,PT2 // 0X1000后是FLASH
JHS WFLASH // 写数据段A,B或程序FLASH
WRAM:
MOV.B @PT1+,0(PT2)
INC PT2
DEC.B B
JNZ WRAM
jmp snp_ACK
WFLASH:
CMP #0FC00H,PT2 // 最后的1KB是核心区,禁止写。
JHS snp_NAK
RRA B // 写FLASH需一次写一个字。
DINT
CALL #DXflash_FLASH
JMP snp_ACK
SPI_Burst_READ:
SPI_WRITE_HEADER:
SPI_Burst_WRITE:
snp_BSF:
snp_CSF:
snp_ASF:
BRET:
RET 楼主厉害! // 有一些对象,它只包含有方法(函数),我们称这种对象为元件。把多种元件放在一起就组成了元件
// 方法库,称为类库,简写:LK。类库中的函数可被多个对象调用,这样可减少代码量。
// 上一次的2个调用要修改为: CALL #LKflash_RASE // 擦洗一段.
// CALL #LKflash_FLASH
//============================================================================================
// LKflashFLASH元件方法库:
//--------------------------------------------------------------------------------------------
// 256字节的FLASH数据空间分为2段(01000H--010FFH)128字节/段。程序段空间分为2段或8段,512字节/段.
// 擦拭后各位为1,可在任意时刻写为0. 只有段擦拭或全部擦拭.
// 只能在非写入或编程时访问存储单元
// 片内FLASH的读写与保护:
// 1000H---107FH: 数据段B.
// 1080H---10FFH: 数据段A.
// F800H---FFDFH: 程序段0,1,2,3
// FFE0H---FFFFH: 中断向量区. INT VECTOR.
// 通过串行移入JTAG的指令来激活加密熔丝,一旦激活,JTAG就不可再访问.
// 在FLASH存储器编程时不允许中断请求. 进入低功耗方式会影响编程时钟要注意!
// F_FTG=257--476KHZ, 设F_FTG=4.096MHZ/10=409.6KHZ.
// t(word write) = 35 x 1/f(FTG)=0.088MS
// t(segment write, WORD 0) = 30 × 1/f(FTG)=0.073MS
// t(segment write, WORD 1 – 63) = 20 × 1/f(FTG)=0.0488MS
// T(segment write,WORD 0 -- 63) = 0.073ms + 63*0.0488ms = 3.1474ms
// T(word 0 -- 63, write) = 64*0.088 = 5.632ms
// t(mass erase) = 5297 x 1/f(FTG)=12.93MS
// t(page erase) = 4819 x 1/f(FTG)=11.765MS
// Program/Erase endurance 10^4 10^5 cycles
// VCC(PGM/ERASE) Program and Erase supply voltage 2.7 3.6 V
// fFTG Flash Timing Generator frequency 257 476 kHz
// IPGM Supply current from DVCC during program 2.7 V/ 3.6 V 3MAX=5 mA
// IERASE Supply current from DVCC during erase 2.7 V/ 3.6 V 3 7 mA
// tCPT Cumulative program time see Note 1 2.7 V/ 3.6 V 4 ms
// tCMErase Cumulative mass erase time see Note 2 2.7 V/ 3.6 V 200 ms
// Program/Erase endurance 104 105 cycles
// tRetention Data retention duration TJ = 25°C 100 years
// tWord Word or byte program time 35 tFTG
// tBlock, 0 Block program time for 1st byte or word 30 tFTG
// tBlock, 1-63 Block program time for each additional byte or word21 tFTG
// tBlock, End Block program end-sequence wait time 6 tFTG
// tMass Erase Mass erase time 5297 tFTG
// tSeg Erase Segment erase time 4819 tFTG
// NOTES: 1. The cumulative program time must not be exceeded when writing to a 64-byte flash block.
// This parameter applies to all programming methods: individual word/byte write and block write modes.
// 2. The mass erase duration generated by the flash timing generator is at
// least 11.1ms ( = 5297x1/fFTG,max = 5297x1/476kHz). To achieve the required cumulative mass erase time
// the Flash Controller’s mass erase operation can be repeated until this time is met.(A worst case
// minimum of 19 cycles are required).
// 3. These values are hardwired into the Flash Controller’s state machine (tFTG = 1/fFTG).
//----------------------------------------------------------------------------------------
// 段擦拭子程序:
// 如果是主存擦拭,则程序放在信息区.
// PT2指向段地址.
//----------------------------------------------------------------------------------------
LKflash_RASE:
TT_BUSY1:
BIT #BUSY,&FCTL3
JNZ TT_BUSY1
MOV #FWKEY,&FCTL3 // 清除LOCK位.
MOV #FWKEY+ERASE,&FCTL1 // (段擦拭ERASE) (全段擦拭MERAS).
CLR 0(PT2) // 擦拭一个段.
TT_BUSY2:
BIT #BUSY,&FCTL3 // 是否忙.
JNZ TT_BUSY2 // 是,继续查.
XOR #FXKEY+LOCK,&FCTL3// 将LOCK位改为1.
RET
//---------------------------------------------------------------------------------------
// 段编程子程序:
// 软件与编程的地址在不同的存储器模块上.
// 数据在PT1所指,PT2指向FLASH,长度在B中.
//---------------------------------------------------------------------------------------
LKflash_FLASH:
T_BUSY1:
BIT #BUSY,&FCTL3
JNZ T_BUSY1
MOV #FWKEY,&FCTL3 // 清除LOCK位.
MOV #FWKEY+WRT,&FCTL1 // 允许编程.
MOV @PT1+,0(PT2) // 编程一个字.
INCD PT2
DEC.B B
JNZ T_BUSY1 // 耒完成继续.
MOV #FWKEY,&FCTL1 // 复位编程.
T_BUSY2:
BIT #BUSY,&FCTL3 // 是否忙.
JNZ T_BUSY2 // 是,继续查.
XOR #FXKEY+LOCK,&FCTL3// 将LOCK位改为1.
RET
擦,还是汇编的,楼主厉害呀 汇编功夫了得 //===========================================================================
// Using the MSP430 as a Real-Time Clock
//===========================================================================
// 实时100年日历时钟子程序.
// 1S看门狗定时器中断.
// MIAO equ 026Ch // Byte for counting seconds
// FEN equ 026Dh // Byte for counting minutes
// XSH equ 026Eh // Byte for counting hours
// XQ equ 026FH // 星期.
// RI equ 0270H // 日.
// YUE equ 0271H // 月.
// NIA equ 0272H // Year –
// NIANG EQU 0273H // 20
//
//---------------------------------------------------------------------------
// Clock_W// Subroutine provides a decimal clock: 00.00.00 to 23.59.59
//---------------------------------------------------------------------------
// Clock Counting Routine:
// Update clock SEC and MIN and HR
// 使用: A // 代码长71字.
// 注意: 年月是十六进制;事件处理没加上。
//----------------------------------------------------------------------------
WDT_ISR:
BIS #MMUJ_BV,SR1 // 置秒事件。周期睡眠;
SETC // Entry every second
DADC.B MIAO // Increment seconds
CMP.B #060H,SR1 // One minute elapsed?
JLO CRET // No, return (C = 0)
CLR.B MIAO // Yes, clear seconds (C = 1)
DADC.B FEN // Increment minutes with set carry
BIS #FGUJ_BV,SR1 // 置分事件。
CMP.B #030H,FEN // 等于30分钟吗?
JNZ CL1
BIS #FG3UJ_BV,SR1// 置30分事件。
CL1:
CMP.B #060H,FEN //
JLO CRET
CLR.B FEN
DADC.B XSH
BIS #XUUJ_BV,SR1 // 置小时事件。
CMP.B #024H,XSH
JLO CRET
CLR.B XSH // 00.00.00 Return to caller
DADC.B XQ // 星期加1
CMP.B #007H,XQ
JLO CL2 // C=0.
MOV.B #0,XQ // Yes, 星期日 (C = 1)
CL2 SETC //
DADC.B RI // 日加1.
BIS #RIUJ_BV,SR1 // 置日事件。零点消息。
MOV.B YUE,A // month->A
MOV.B MT(A),A // 当月的日数->A
CMP.B #2,YUE // February now?
JNE CLC2
BIT.B #3,NIA // Yes, Leap Year?
JNZ CLC2
DADD #1,A // Yes, 29 days for February
CLC2 CMP.B A,YUE // One month elapsed?
JLO CRET // C=0,返回.
MOV.B #1,RI // Yes, 1日 (C = 1)
INC.B YUE // of next month
BIS #YVUJ_BV,SR1 // 置月事件。
CMP.B #13,YUE // Year over?
JLO CRET // No
MOV.B #1,YUE // Yes, 1月 (C = 1)
INC NIA // of next year
BIS #NYUJ_BV,SR1 // 置年事件。
CRET:
RETI
// Table with the length of the 12 months
MT:
DB 32H,28H,32H,31H,32H,31H// January to June
DB 32H,32H,31H,32H,31H,32H LZ想作甚 额,把面向对象延伸进汇编实属不易,绝对的大神 MARK
MARK
页:
[1]