PICNIC

指南(课题0)

■ 指南(課題0)

1. 指南的目标

2. 程序存储器使用状况与页面间的转换

3. 关于固件ver1.2.0.4

4. dummy模块的call/return

5. 门传感器→LED•继电器输出

6. 在家•外出模式的导入

7. 課題0的提交

■报告提交系统

 

→提问•讨论用的BBS

←返回目录

2006年4月5日 16:27 更新

 

●指南的目标

在本指南中,针对

dummy模块的call/return(实验1,2)
门传感器—LED继电器的输出(实验3—7)

边参照程序例边进行说明。

最后,作为课题0(实验8),请编程安装
[考虑在家,外出模式的门敞着警报钟]
功能,并提交此课题。

●程序存储器使用状况与页面间的转换

肯定有人会想,把一直到课题0的代码直接插入主循环的main0~main99之间就可以了吧。虽然可以想象大家急切的心情,但是还请稍等一下

如果直接在main0之后配置新代码,那么在写入了一定程度的编码后就会出现,要么web控制页面变得不应答,要么HTML控制页面只能显示到中途,要么浏览器的「接收中」图标一直处于接收中状态等症状,即变的「不安定」。

<故障的原因>

在现固件的配置中,程序存储器page#0几乎用到了边界。

程序存储器使用状况:

page#0 : 0x0000-0x07FF : 0x0000--0x07EA 利用中
page#1 : 0x0800-0x0FFF : 0x0820--0x0FED 利用中
page#2 : 0x1000-0x17FF : 0x1000--0x1240、0x1300--0x13FB、0x1400--0x14EB
0x1700--0x17FF 利用中
page#3 : 0x1800-0x1FFF : 0x1800--0x185A、0x1A00--0x1B19、0x1D00--0x1DA5
0x1F00--0x1FC1 利用中

例如,page#1的put_socket_stat模块(向web浏览器传送套接字(socket)的状态(所谓的netstat-n))被改为注释。这是因为page#1容量已满,不删除的话,就无法储存page#1中的别的模块。在进行固件开发时,可以把一个字节想象成一滴血,尽可能有效地利用有限的程序存储器空间。

<解决方法>

在保证现有功能的前提下,作为存放追加模块的领域只有
page#3 1E00h--1EFFh 256字节

不过因为这个也紧接在web信息的BANK#4之后,所以要充分注意这个BANK#4的信息量不要超过256字节。

在下面的指南中,从这个1E00h开始安装用于实验的模块,为了确认功能,紧接在main0标签之后,写入一段用来「横跨页间」调用实验用模块的编码。

(PIC16F87x拥有4个程序存储器页。不知道的同学请从这儿返回复习(参照11页))

那么,就进行具体地编写。

●关于固件ver.1.2.0.4 (2004/10/30修正)

第4章 固件的更新操作中,我们对原版的ver1.2.0.0(v12.asm)的

・固件版本的更新
・在web控制页面的末尾(web信息的BANK#4的最后)追加一行

进行了的改善,更新成为了ver1.2.0.1。

ver1.2.0.0 ※特别发布
ver1.2.0.1 更新履历0.0→0.1

此后,经过各种微小变动,更新出了作为这个指南的「出发点」的ver1.2.0.4(b)版本

ver1.2.0.2 更新履历0.1→0.2
ver1.2.0.3 更新履历 0.2→0.3
ver1.2.0.4 更新履历 0.3→0.4
ver1.2.0.4(a) 更新履历 0.4→0.4(a)
ver1.2.0.4(b) 更新履历0.4(a)→0.4(b)

最新版本的web控制页面从这儿进入
※ 以http://192.168.1.200:8080/获取

在以下的指南中,是以对ver1.2.0.4(b)的固件进行改造为前提。当然,对原版的固件(ver1.2.asm)进行改造也是可以同样动作的,请安心。

从这儿下载最新版本的固件(2004年10月30日修正 v1204org.asm)

※注意点
默认的IP地址:http端口号被改为

・IP地址:192.168.1.200(不是0.200)
・http端口:8080(不是80)

故在使用这个固件雏形时,操作用PC的网段请设定为如:

・IP地址:192.168.1.10
・网络掩码:255.255.255.0

(无所适从的同学请从这儿返回进行复习)


※2003/10/12修正(a):
在2003年9月8日做成的v1204org.asm中,HTML应答部分的\r\n
的后面会生成不用的0x00,由于这个影响,某些web浏览器(Netscape7.1等)就不
认为它是text/html型而引起错误
。由此,把HTML应答部分改为了利用DA伪指令进
行一次性输出。给大家添了麻烦,很抱歉。

※2004/10/30修正(b):
在v1204org(a).asm中,由于在556行包含有MPASM伪指令,因此用面向MacOS的
GNUPIC (gpasm)进行汇编时会出现故障
,删除了此行。

●Dummy模块的call/return

【实验1】 dummy模块的作成
【实验2 】STATUS寄存器保护版dummy2模块的作成


e0.4.1【实验1】 dummy模块的作成

试着制作dummy模块

<规格>
包括在别的页面(page#3,1E00h~)上作成dummy模块。然后针对它的所在页面进行页面切换后调用(call),最后返回到main1标签的功能。

<动作>
没有特别的变更

<处理概要>
关于跨越程序存储器页间的调用,其基本的处理顺序如下:

・要知道调用模块的页面位置(#0~#3)
・页面选择寄存器的设定
・页面选择寄存器的清零(依存于现在的页面位置)

<编码>
具体的编码如下:

+++++++++++++++++++++++++++++
page#0
+++++++++++++++++++++++++++++
main0
movlw HIGH (dummy) ; dummy >> 8 读取页面位置
movwf PCLATH ; 设定页面选择寄存器
call dummy ; 调用dummy模块
clrf PCLATH ; 页面选择寄存器的清零
main1
......
+++++++++++++++++++++++++++++
PAGE#3
+++++++++++++++++++++++++++++
org 1E00h
dummy
nop
return
+++++++++++++++++++++++++++++

【call dummy调用侧】
在第860行附近可以找到main0标签(程序存储器page#0)。从main0标签到main99标签前的get_packet模块之间是主循环(周期性地执行这段编码)。紧接main0标签的之后,追加上述的由4个步骤实现的调用处理。

※注意点:对于在调用dummy模块之侧追加的4行,请务必直接放在main0标签之后。因为如果在这个位置,一定会被定期执行的。(2005/5/3追记)

 

【dummy模块的编码位置】
Dummy模块的编码位置是,第7243行附近的程序存储器page#3, web浏览器用•信息和EEPROM数据的初始值之间,因它是执行指令org 1E00h的适当位置,故可在此间编码。Dummy模块是仅执行nop命令(不做任何动作)后就返回的处理。

 

【実験1】
从main0侧的调用,以及对dummy模块的编码,然后确认其是否正常动作。由于因为dummy不做任何的操作就返回,所以应该与先前的ver1.2.0.4的动作没有变化。

 


e0.4.2 【实验2】STATUS寄存器保护版dummy2模块的作成

假如实验1顺利动作了话,接着就作成STATUS寄存器保护版dummy2模块

<规格>
因为与中断例行程序不同,即使在main0附近,W寄存器,FSR等被更改也不会出现问题,所以目前觉得在dummy内部的上下文(context)保护•复原处理是不需要的。但是,对STATUS寄存器的变更有时会引起问题,故追加一个在执行call处理之后保护STATUS寄存器,然后再在返回之前复原STATUS寄存器的处理。

<动作>
没有特别的变更。

<处理概要>
使用通用变量wk2进行STATUS寄存器的存放(wk2 07FH)

从任意一个寄存器体BANK#0--#3来看wk2都是一样的,非常方便。
microchip/30292a-j.pdf#page=13

在中断例程内,由于使用的不是初始化的wk2,所以必须先对wk2进行回避处理后才能使用wk2。但是,在现有的固件中,dummy2被调用的期间wk2没有被使用,所以就不需要对wk2进行回避处理,直接用来处理STATUS寄存器的保护(←有点繁杂但务必理解)。

理所当然,因为是回避从STATUS寄存器到wk2的值,在执行复归STATUS期间,wk2是不可以变更的。

<实际配置>
具体地实际配置如下所示:

+++++++++++++++++++++++++++++
PAGE#0
+++++++++++++++++++++++++++++
main0
movlw HIGH (dummy) ; dummy >> 8 读取页面位置
movwf PCLATH ; 设定页面选择寄存器
call dummy ; 调用dummy模块
clrf PCLATH ; 设定页面选择寄存器
main1
......
+++++++++++++++++++++++++++++
PAGE#3
+++++++++++++++++++++++++++++
org 1E00h
dummy2
; STATUS回避处理
swapf STATUS, 0 ; 保存STATUS寄存器
clrf STATUS ; 设定STATUS为0
movwf wk2 ; 回避至wk2
nop ; 空操作
; STATUS复归处理
swapf wk2,0
movwf STATUS ; 复归status
return
+++++++++++++++++++++++++++++

那么,在执行STATUS寄存器回避处理期间(执行nop的位置),执行一下STATUS的RP0,RP1字节也没有关系。这样,面向接下来的实验的雏形已经完成了:-)

【実験2】
从main0侧调用以及实际配置STATUS寄存器值保持版的dummy2模块,确认其是否正常动作。由于即使调用了dummy2也不做任何的操作就返回了,所以与先前的ver1.2.0.4的动作一定是没有变化的。

 

●门传感器→LED•继电器输出

【实验3】到RB4(LED#4)的既定值("H")输出 test1模块的制作
【实验4】RB0(门传感器)→到RB4(LED#4)输出test2模块的制作
【实验5】RB0(门传感器)→到RB4(LED#4)负逻辑输出 test2a模块的制作
【实验6】RB0(门传感器)→到RB7(Relay#2)负逻辑输出 test2b模块的制作
【实验7】RB0(门传感器)→到RB4正逻辑&到RB7负逻辑输出 test2c模块的制作


e0.5.1 【实验3】到RB4(LED#4)的既定值("H")输出 test1模块的制作

作为输出到PORTB值的练习,让我们来制作可以执行到RB4(LED#4)的既定值("H")输出 test1模块

<规格>
到RB4(LED#4)的既定值("H")输出

<动作>
在复位后,RB4=High(LED#4亮)

<处理概要>
RB4被分配到寄存器库BANK#0 or #2 的PORTB[bit4]。
microchip/30292a-j.pdf#page=13

到寄存器库BANK#0 or #2的切换,只要清除STATUS寄存器的RPO字节就行了。

要把PORTB[bit4]设定成H,只要在movf中,首先引导PORB,用OR逻辑强制把bit4设定成H,然后再重写到PORTB的值就行了。

<实际配置>
具体地配置如下所示:

另外,以后对于main0侧的变更处以及模块先头,最后的STATUS维护处理全部省略。下面的4行是更换dummy2的nop的。

当然,模块登录标签不是dummy2,使用test1。

         org 1E00h
test1
............ ; 回避STATUS
bcf STATUS,RP0 ; 寄存器BANK#0/2
movf PORTB,0 ; 输入PORTB→regW
iorlw B'00010000' ; 设定RB4为H
movwf PORTB ; regW→PORTB的输出
............ ; 复归STATUS
return

这样,即使指示的是RB4=L,通常也保持H状态。(从web控制页面指示的话,好像会在一瞬间显示“L|”)

【実験3】
从main0侧调用以及实际配置test1模块,确认其是否正常动作。确认RB4是否保持为H。由于别的地方无需变更,只要返回就行了,所以与先前的ver1.2.0.4的动作一定是没有变化的。

 


e0.5.2【实验4】RB0(门传感器)→到RB4(LED#4)输出test2模块的制作

下面,作为条件分支命令的复习,制作能够把RB0(门传感器)的状态值原样输出到RB4(LED#4)的test2模块。

<规格>
※ 端口分配:
PORTB[0](RB0):输入(门传感器・门关闭状态的时候"H")
PORTB[4](RB4):输出(LED#4 门状态表示灯・门关闭状态的时候"亮")

RB0(门专感器)→到RB4(LED#4)得输出(正逻辑)

<动作>
作为动作,要求有如下这样:
・门開着(RB0=="L")→LED#4消灯(RB4:="L")
・门关着(RB0=="H")→LED#4点灯(RB4:="H")
输出一直可以反映门传感器的状态。

<处理概要>
RB0,4被分配给寄存器库BANK#0 or #2的 PORTB[bit0]以及[bit4]。
microchip/30292a-j.pdf#page=13

到寄存器库BANK#0 or #2 的切换,与实验3一样,删除STATUS寄存器的RP0字节就行了。

PORTB[0](RB0)的状态检查
if (PORTB[0](RB0) == H)
PORTB[4](RB4) := "H"
else
PORTB[4](RB4) := "L"
endif

检查PORTB[bit0]的状态,可以在movf中,首先以PORTB为引导拷贝到操作用程序存储器wk1,通过对其bit的检查来实现。(btfsc命令等)(为了避免W寄存器的损坏)

W寄存器的保存使用通用变量wk1(wk1 07EH)。
可以从任意一个寄存器库BANK#0--#3读取wk1。
microchip/30292a-j.pdf#page=13

・把PORTB[bit4]设定成H的方法与实验3同样(用OR逻辑强制地把bit4变为H)
・把PORTB[bit4]设定为L的方法是,在根据AND逻辑的字节掩码强制地把bit4设定为L之后,恢复(写入)到PORTB的值就行了。

<实际安装>
具体地安装如下所示:

         org 1E00h
test2
............ ; 回避STATUS
bcf STATUS,RP0 ; 寄存器BANK#0/2
movf PORTB,0 ; 输入PORTB→regW
movwf wk1 ; 拷贝至wk1
btfsc wk1,0 ; 检查RB0的位
goto test2_01
andlw B'11101111' ; 设定RB4为L
goto test2_02
test2_01
iorlw B'00010000' ; 设定RB4为H
test2_02
movwf PORTB ; 输出regW→PORTB
............ ; 复归STATUS
return

这样,RB0(门传感器)的状态值就可以原样地输出到RB4(LED#4)了。(也就是,门关闭时,LED#4灯亮)

【実験4】
从main0侧调用以及实际配置test2模块,确认其是否正常动作。确认RB0(门传感器)的状态是否原样地输出到RB4(LED#4)了(门关闭时,LED#4亮灯)。

 


e0.5.3【实验5】RB0(门传感器)→到RB4(LED#4)负逻辑输出 test2a模块的制作

改造test2模块,制作能够把RB0(门传感器)的状态值,作为负逻辑输出到RB4(LED#4)的test2a模块。也就是,作为安全防盗系统可以看作,定义与test2相反的功能,在门被打开的时候(危险时)灯能够亮(=门打开警报)

<规格>
RB0(门传感器)→到RB4(LED#4)的输出(负逻辑)

<动作>
作为动作,象下面这样:
・门开着(RB0=="L")→LED#4灯亮(RB4:="H")
・门关着(RB0=="H")→LED#4灯亮(RB4:="L")
作为「门打开时的警报灯」时的输出。

PORTB[0](RB0)的状态检查
if (PORTB[0](RB0) == L)
PORTB[4](RB4) := "H"
else
PORTB[4](RB4) := "L"
endif

 

【実験5】
实际配置上述那样规格的test2a模块、确认作为「门打开时的警报灯」是否能够正常动作。

<提示>
把对应于门状态值的条件转移的逻辑相反就行了。

(变更前)
 btfsc wk1,0 ; RB0的位检查

(变更后)
 btfss wk1,0 ; RB0的位检查

 


e0.5.4【实验6】RB0(门传感器)→到RB7(Relay#2)负逻辑输出 test2b模块的制作

<功能>
当门被打开时(危险时)LED#7亮灯,鸣放警报(=门打开警报)

<处理>

PORTB[0](RB0)的状态检查
if (PORTB[0](RB0) == L)
PORTB[7](RB7) := "H"
else
PORTB[7](RB7) := "L"
endif

 

【実験6】
实际配置上述那样规格的test2b模块、确认作为「门打开时的警报灯」是否能够正常动作。

<提示>
作为到RB4的字节操作替代,执行到RB7的位操作就行了。

(变更前)
andlw B'11101111' ; 把RB4设定为L
iorlw B'00010000' ; 把RB4设定为H

(变更后)
andlw B'01111111' ; 把RB7设定为L
iorlw B'10000000' ; 把RB7设定为H

 


e0.5. 5【实验7】RB0(门传感器)→到RB4正逻辑&到RB7负逻辑输出 test2c模块的制作

<功能>
监视RB0(门传感器)的状态,执行在门关闭状态亮灯⇔在门打开状态鸣放警报的动作。

RB0(门传感器)
→到RB4(LED#4)是正逻辑(在门关闭状态时亮灯)
→到RB7(Relay#2)是负逻辑(在门打开状态时鸣放警报)

<処理>

PORTB[0](RB0)的状态检查
if (PORTB[0](RB0) == L)
PORTB[7](RB7) := "H"
PORTB[4](RB4) := "L"
else
PORTB[7](RB7) := "L"
PORTB[4](RB4) := "H"
endif

 

【実験7】
实际配置上述那样规格的test2c模块、监视RB0(门传感器)的状态,确认在门关闭时亮灯⇔门打开时鸣放警报,这样的功能是否能够正常动作。

<提示>
在以test2b为基础的场合,与到RB7的位操作并用,执行到RB4的位操作就行了。

(変更前)
andlw B'01111111' ; 把RB7设定为L
(变更后)
andlw B'01111111' ; 把RB7设定为L
iorlw B'00010000' ; 把RB4设定为H

(変更前)
iorlw B'10000000' ; 把RB7设定为H
(变更后)
iorlw B'10000000' ; 把RB7设定为H
andlw B'11101111' ; 把RB4设定为L

 

●在家•外出模式的导入

【实验8】(课题0)根据在家•外出模式切换报警动作的test3模块的制作
复位时初始值(RB5=Low)的时候,对设定为「外出模式」的观测


e0.6.1【实验8】(课题0)根据在家•外出模式切换报警动作的test3模块的制作

<规格>
RB5(Mode#2)作为在家•外出模式的状态切换

Low的时候:外出模式(复位时的初始值)
High的时候:在家模式

对应于这个在家•外出模式执行如下动作:

RB0(门传感器)
→RB4(LED#4):在门关闭状态时亮灯(与模式无关)
→RB7(Relay#2):RB0==Low && RB5 == Low 时、在门打开状态时警报鸣放(外出模式时)

<动作>

对应在家•外出模式

・在家时,门状态通过LED#4可以确认
・外出时,门被打开的话,使其鸣放警报

【実験8】(课题0)
制作上述那样规格的test2c模块、确认其动作。

※编写程序时的注意点:请务必在汇编码各行处,写上表示这一行动作的简短注释。即使是编写程序的本人,在经过2~3天后,也会忘了,特别是分支命令的名称,因为容易混肴的很多(btfsc,btfss等),对分支条件等请特别慎重地写上注释。添加注释可能会认为是无用浪费,但是即使在程序开发的流程中,也是一个重要的因素(→参考Javadoc的例子


e0.6.2 复位时初始值(RB5=Low)的时候,对设定为「外出模式」的观测

(A)初始值(Low)时,设定成「在家模式」的场合

在外出时,不知何原因软件被复位,发生了停电的场合,在恢复后,由于初始值为Low,成为「在家」状态,门打开报警功能无法动作。

(B)初始值(Low)时,设定成「外出模式」的场合

相对于(A),软件复位或者停电恢复后,由于初始值为Low,为「外出」,门打开警报功能可以继续动作。

(C)关于停电时的应急电源

假如用AC插头直接插在商用电源插座上,直接供电的场合,在停电期间,门开放警报「不鸣放」。为此,为了完善PICNIC+周边选择套间+网络连接环境,应该配置不间断电源装置(UPS)。

●课题的提交

(1)完成§E0.6.1【实验8】(课题0)根据在家•外出模式切换报警动作的test3模块的制作

(2)利用门传感器状态,web控制页面上的RB5状态变化功能,确认是否按照规格正常动作

(3)变更汇编源程序文件的版本编号ver1.2.0.4 --> ver1.2.0.5
另外,把web控制换面的封面部分,适当地变更为自己的学籍编号等。

(4)把完成的汇编源程序文件以v1205e0.asm命名保存(全部使用半角英文字母数字•字母用小写,半角日文片假名•绝对不可以使用全角文字命名文件名)

(5)从以下的报告提交系统,上传v1205e0.asm ,在接收到报告后进行评分。

<提交方法>
利用报告提交系统(具有文件上传功能),提交编写的程序中的汇编•源程序文件(后缀为*.asm的文件。不是*.hex) 

提交的文件,在经过动作确认后,假如有动作不良的场合需要再次提出,动作ok的场合,评判为完了。

报告课题0(课题编号:picnic-exp00)的提出从这儿进入

(6)显示「等待评判」,请稍微等待。评判结果长时间不出来的场合,请发送邮件至这儿。

(7)被评判为再次提出的场合,修改指出的不完善的地方,更改v1205e0a.asm等文件名,再次提出。

(8)不是(7)的场合(评判为完了),报告课题0被受理,完了

信州大学インターネット大学院

wasaki@cs.shinshu-u.ac.jp
Copyright(c) 2005 Katsumi Wasaki. All rights reserved.