FPPA 程式設計 這一章開始正式進入FPPA程式設計的世界,我會從一個簡單的程式開始解說,一邊介紹專案開發時最常應用的技巧還有程式控制的手段,一邊把系統規畫的概念導入給大家,讓大家對專案的規畫能有一個初步的概念。

Slides:



Advertisements
Similar presentations
嵌入式系统与单片机 北京科技大学电子信息系.
Advertisements

松翰科技 — 全新高性能 8-bit 微控制器
6 单片机的中断与定时系统 I/O设备必须通过I/O接口与计算机连接。 I/O接口的功能: 1.速度匹配: 锁存数据、传送联络信号。
单片机应用技术 项目一 循环彩灯装置 第7讲 Keil软件的使用 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
最新計算機概論 第3章 計算機組織.
Arduino单片机基础及开发应用 姜凯耀
2017/3/22 如何用C 来完成SN8系列芯片的程序设计 2017/3/22.
本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
PLC控制系统设计与运行 模块二:灯光的PLC控制 主讲教师:吴会琴.
5-3 8x8矩陣LED控制實習.
8051 指令.
題目:LED電子數位時鐘 第 二組 組員: 陳柏霖 李育昇.
第 2 章 中央處理單元.
第四章 指令系统及汇编语言程序设计.
项目2 2个LED发光二极管控制 知识与能力目标 熟悉单片机的I/O口功能与特性。
得技通电子 问题 1 右何者非為假指令 (1) XRL (2) EQU (3) MACRO (4) ORG.
4-10 STM Timer/Counter 與比較吻合輸出
第5章 中央處理單元與主記憶體 5-1 中央處理單元-CPU 5-2 主記憶體.
第7章 中斷系統.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月26日.
项目成果展示 ——深圳凯吉尔科技—— 凯吉尔全线代理无锡研奥产品 说明:
PIC16F1827介紹 以微控器為基礎之電路設計實務-微處理器實驗室.
第9章 串行扩展技术 (课时:6学时).
Timer & KEYPAD 11/24.
第2章 MCS-51单片机指令系统与汇编语言程序设计
第二部分 微机原理 第4章 汇编语言 程序设计 主讲教师:喻红.
本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
第8章 模拟接口 8.1 模拟接口概述 8.2 DAC及其接口 8.3 ADC及其接口.
指令集架構 計算機也跟人類一樣,需要提供一套完整的語言讓人們跟它充分溝通,以完成正確的計算工作。
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年12月10日.
1-1 微電腦系統單元 1-2 微電腦系統架構 1-3 微控制器(單晶片微電腦) 1-4 類比與數位訊號介面
1-1 微電腦系統單元 1-2 微電腦系統架構 1-3 微控制器(單晶片微電腦) 1-4 類比與數位訊號介面
课程:《单片机原理及应用》 教材:《单片机原理及应用》 学时:理论32+实验32=64 教学内容与要求:见教学大纲
第6章 MCS - 51单片机内部定时器/ 计数器 及串行接口 6.1 定时器/计数器的结构及工作原理 6.2 方式和控制寄存器
單晶片微電腦控制實習 使用計時中斷作走馬燈 計時器的基礎實習 國立大甲高工 電機科 2018年11月21日
第六部分 ADSP-2189M EZ-KIT评估套件 a.
5 Computer Organization (計算機組織).
第七章 MCS-51系统扩展 一、程序存储器扩展
Operating System Concepts 作業系統原理 CHAPTER 2 系統結構 (System Structures)
第十一章 复位、时钟和省电方式控制.
第八章 输入输出程序设计 总线 CPU MEM I/O接口 I/O设备.
Operating System Internals and Design principles
HOLTEK 产品 在小家电的应用.
第一章 C語言概論 本章投影片僅供本書上課教師使用,非經同意請勿拷貝或轉載.
微处理器设计2 刘鹏 College of ISEE Zhejiang University
一个非常简单的CPU的设计 1、组合逻辑控制器 2、微程序控制器.
第一章 8086程序设计 第二章 MCS-51程序设计 第三章 微机基本系统的设计 第四章 存贮器与接口 第五章 并行接口
第2章 单片机系统组成原理 2.1 MCS-51单片机组成原理 2.2 单片机复位电路设计 2.3 MCS-51存储器配置
6.1 输入/输出 6.2 CPU与外设数据传送方式 6. 3 MCS-51中断系统 6. 4 中断应用举例
合泰半导体股份有限公司 技术讲座 - Holtek V3 C Compiler介绍 主讲人:王幼端 2017/06/15.
4-15 WDT HT66F50.
Holtek C Compiler V3--advanced
(第2版).
8051單晶片 蘇恆生 老師.
亚博科技 Arduino视频教程 第8讲 蜂鸣器发声实验.
通訊實驗 實驗三 遙控車程式流程圖 姓名:顏得洋 學號:B
微机原理与接口技术 西安邮电大学计算机学院 王忠民.
5-6 串列埠模式0輸出埠擴充實習.
单片机原理与应用 主讲人:张荣刚 福建师范大学福清分校.
4-9 Timer/Counter 控制七段速度
K60入门课程 06 首都师范大学物理系 靳熙芃.
第三章 计算机系统的组成与工作原理.
汽车单片机应用技术 学习情景1: 汽车空调系统的单片机控制 主讲:向楠.
四、手工汇编 完成汇编的方法有两种:手工汇编和汇编程序汇编 1.手工汇编步骤 A
利用HT66F50 SIM模組單元中PCK腳位輸出特性 控制speaker 發聲 SIM 串列界面模組
4.11 ADC.
第4章 MCS-51汇编语言程序设计 教学基本要求: (1)、了解MCS-51汇编语言程序设计的特点;
单片机原理及接口技术 前修课程:数模电、微机原理.
FPPA 程式架構.
新選課系統說明會 電算中心 林以仁.
Presentation transcript:

FPPA 程式設計 這一章開始正式進入FPPA程式設計的世界,我會從一個簡單的程式開始解說,一邊介紹專案開發時最常應用的技巧還有程式控制的手段,一邊把系統規畫的概念導入給大家,讓大家對專案的規畫能有一個初步的概念。

常用指令介紹 set0 bit ;位元設0 set1 bit ;位元設1 tog iobit ;位元0/1切換 call addr ;呼叫副程式 goto addr ;跳躍到標籤 delay x ;延時 x+1 指令周期 ceqsn x,y ;if x=y skip t0sn bit ;if bit=0 skip t1sn bit ;if bit=1 skip dzsn x ;x-=1, if x=0 skip wait0 iobit ;等待直到 bit=0 wait1 iobit ;等待直到 bit=1 clear x ;x=0 mov x,y ;x=y inc x ;x+=1 要學習 FPPA 程式設計可以從幾個地方開始著手… 一、原廠 Datasheet。 二、FPPA指令集.doc 以及原廠光碟 Instructions Example code 目錄,有每個指令的簡單範例。 三、原廠光碟 Training Course 目錄,有 Assembler 的基本介紹跟一些程式流程的控制方法,譬如判斷等於大於小於、迴圈的用法…。 四、原廠光碟 Application Note 目錄,有提供一些專案常常會用到的周邊界面的程式範例,很有參考價值。 這些內容很詳細很豊富但是也很多,需要很多時間來學習,建議是先大略看過一遍,等有需要再去回頭去參考就好了。 這邊只介紹幾個「必學」的指令,這些指令算是最基本也最常用到的。 注意 iobit 跟一般 bit 的差別。 IDE簡介。

輸入控制-按鍵 buttonLoop: wait0 BTN0; // TODO goto buttonLoop; /// -------- PORTA ------- 0b76543210 SET_PORTA equ 0b11111110; SET_PORTA_PH equ 0b11111111; BTN0 equ pa.0; LED0 equ pa.1; … mov a, SET_PORTA; /// PA IO direction mov pac, a; mov a, SET_PORTA_PH; /// PA pull-high mov paph, a; buttonLoop: wait0 BTN0; // TODO goto buttonLoop; MCU 重點解說: 打開新專案樣板,開始寫第一個程式。 IO腳位的設定。 TODO 包含了執行按鍵的動作跟等待按鍵放開。 ICE實作,執行,詢問大家是否沒問題,有自己在家測試過? Wait Button Press TODO 程式碼:4FPPA程式設計-1-1按鍵.asm

按鍵彈跳的問題 HI LO 約3-5ms 作為一個按鍵從沒有按下到按下以及放開是一個完整的過程,也就是說,當我們按下一個按鍵時,希望某個命令只執行一次,而在按鍵按下的過程中,不要有干擾進來,因為,在按下的過程中,一旦有干擾過來,可能造成誤觸發過程,這並不是我們所想要的。因此在按鍵按下的時候,要把我們手上的干擾信號以及按鍵的機械接觸等干擾信號給濾除掉,一般情況下,我們可以採用電容來濾除掉這些干擾信號,但實際上,會增加硬體成本及硬體電路的體積,因此我們可以採用軟體濾波的方法去除這些干擾信號,一般情況下,一個按鍵按下的時候,總是在按下的時刻存在著一定的干擾信號,按下之後就基本上進入了穩定的狀態。具體的一個按鍵從按下到釋放的全過程的信號圖如上圖所示 從圖中可以看出,我們在程序設計時,從按鍵被識別按下之後,延時3-5ms以上,從而避開了干擾信號區域,我們再來檢測一次,看按鍵是否真得已經按下,若真得已經按下,這時肯定輸出為低電位,若這時檢測到的是高電位,證明剛才是由於干擾信號引起的誤觸發,CPU就認為是誤觸發信號而捨棄這次的按鍵識別過程。從而提高了系統的可靠性。 由於要求每按下一次,命令被執行一次,直到下一次再按下的時候,再執行一次命令,因此從按鍵被識別出來之後,我們就可以執行這次的命令,所以要有一個等待按鍵釋放的過程,顯然釋放的過程,就是使其恢復成高電位狀態。

按鍵防彈跳 buttonLoop: wait0 BTN0; call DoButton0; goto buttonLoop; call Delay4ms; t0sn BTN0; ret; // TODO wait1 BTN0; Delay4ms: mov a, 16; mov counter, a; delayLoop: delay 250; dzsn counter; goto delayLoop; ret; 接下來的程式,一直延續原來的程式。 介紹 Compare and Merge 基本用法。 副程式呼叫方式,Delay 副程式介紹,delay 時序的計算後面會提到。 程式碼:4FPPA程式設計-1-2按鍵彈跳.asm

程式架構 MCU Wait Button Press Condition TODO 有條件的執行按鍵的動作,亦可看成是執行這段程式的一個種過瀘條件(軟體filter)

實作:按鍵防彈跳 T=1+1+16x(250+1+1+1)-1+1=4050T=4050us Delay4ms: mov a, 16; // T=1 mov counter, a; // +1+16x( delayLoop: delay 250; // +250+1 dzsn counter; // +1 goto delayLoop; // +1) ret; // -1+1 1 1 253 253 253 253 253 253 253 253 253 253 253 重點講解:delay副程式,時間的計算。 程式的目的只有產生一段時間的延遲,並不在要求精確,所以這邊只用一個大略的值,當然你也可以仔細的去調整成準確的4ms,調整的技巧我們後續會提到,不過在這個例子,意義並不大,因此以程式的可讀性跟程式撰寫的方便性來作考量,也是最直覺的寫法。 253 253 T=1+1+16x(250+1+1+1)-1+1=4050T=4050us 253 253 252 1

多按鍵輪詢 buttonLoop: t1sn BTN0 call DoButton0 t1sn BTN1 call DoButton1 … goto buttonLoop DoButton0: call Delay4ms t0sn BTN0 ret // TODO0 wait1 BTN0 DoButton1: call Delay4ms t0sn BTN1 ret // TODO1 wait1 BTN1 輪詢-意即不斷的去檢查輸入的狀態,執行相對應的動作,動作與動作間會有處理優先順序的問題,而且是相依的,也就是若同時有很多按鍵被按下,程式也是按照一定的順序去執行。通常,由於 UI ( User Interface ) 是透過使用者透過按鍵之類輸入的觸動才會作用,一般而言都會有足夠的時間來反應,因此沒有必要特別的把不同的按鍵用多核多工的方式來處理。 程式碼:4FPPA程式設計-1-3多按鍵輪詢.asm

程式架構 MCU Check Button 0 Press Condition TODO Check Button 1 Press

實作:多按鍵輪詢 問題討論:一個按鍵按住的時候另一個按鍵無法動作。 這時候會需要把按鍵再細分成按下跟放開兩種不同的狀況來處理,寫在同一段程序的優點是比較好寫、程序走向比較好掌握,缺點則是按鍵會相依,一個按鍵沒放開,另一個按鍵就無效。(demo),回頭看程式碼。

按鍵狀態細分 buttonLoop: t1sn BTN0 call DoButton0 t1sn BTN1 call DoButton1 … call DoButton0Release t0sn BTN1 call DoButton1Release goto buttonLoop DoButton0: call Delay4ms t0sn BTN0 ret // TODO DoButton0Release: // TODO ret 細分成兩個不同的狀態來寫的話,就不會有這個缺點,但是程式設計時對於事件處理的概念要更清楚。這是一個抽象化的過程,把 IO 的狀態,當成不同的事件來處理,把事件集中起來當成一個物件來處理,這其實也是物件導向程式設計的一個重要方法,有興趣的人可以找相關的書籍來參考。 程式碼:4FPPA程式設計-1-4按鍵事件細分.asm

程式架構 MCU Check Button 0 Press Condition TODO Check Button 1 Press Check Button 0 Release TODO 程式的架構看起來像這樣,其實只是原來的延伸,只不過在輪詢時多處理二種狀況 Check Button 1 Release TODO

實作:按鍵狀態細分 問題討論:在一個系統中,常常會有很多像按鍵這樣子的狀況需要去處理,譬如按鍵輸入(IO觸發)、紅外線輸入、計時器、外部SENSOR的狀況… ,我們都可以用輪詢的方式去檢查系統的狀態來決定要不要做某些事情, 所以事實上,我們可以把這些都整合起來一起處理,寫在一起。

事件觸發 eventLoop: t0sn EVENT0 call ActiveEvent0 t0sn EVENT1 … t1sn EVENT0 call StopActiveEvent0 t1sn EVENT1 call StopActiveEvent1 goto eventLoop 剛剛提到的的一個事件、狀態的概念,事件改變狀態,狀態造成動作,動作可能又引發不同的狀態。 用事件觸發的方式來處理底層 IO 不同的狀態要去執行的不同工作,程式碼寫起來就像這個樣子。程式碼其實是完全一樣,差別只在於,我們在實體 IO 跟程序之間多了一層「狀態」,而程序則是根據不同的狀態來跑程式。 ActiveEvent0: // TODO0 ret ActiveEvent1: // TODO1 ret 程式碼:4FPPA程式設計-1-5事件觸發.asm

狀態控制-事件集中處理 GetEventLoop: clear SET_EVENT t1sn BTN0 set1 SET_EVENT0 … t1sn IR0 t0sn IR0 mov a, SET_EVENT mov EVENT, a goto GetEventLoop 按鍵輸入 IR輸入 其它控制方式 至於狀態的檢查的程式碼也集中寫在一起,主要是檢查IO的狀態,設定相對應的事件。 這樣的好處有二個,一事件集中處理,不同輸入方式可以觸發相同的事件,相同輸入也可以觸發不同的事件。 二、對於按鈕的 low 或 high active 能統一在這裡作修改維護,而不會因為程式有好幾個地方需要作按鍵處理,分散開來,光維護就是個問題了。

程式架構 FPP1 FPP0 Event0 Active Check Event0 Get Event0 Event1 Active 左邊 FPPA1 負責檢查 IO 狀態並且 設定相對應發生的事件,中間 FPP0 則不斷檢查是不是有事件發生,有的話就去執行一段程式。 整個系統把它分成這樣的抽象概念後,就能夠很容易的進行系統分析的工作,並且系統變的能很容易的去增加新功能或刪除某個特定的功能。 Get Event3

程式架構 FPP2 FPP1 FPP0 Event0 Active Check Event0 Process Button Get IR Get Event2 舉個例來說,輸入的部份可以增加IR、觸控面板…甚至是透過PC連線控制、Chip 對 Chip…等等各種不同的操作方式,只要單獨去開發它的界面模組,然後把它對應成系統的事件就可以把界面掛到這個系統。 同樣的概念其實也可以應用在輸出的部份,不同的輸出等於不同的驅動模組。 Get Event3

實作:事件處理 重點講解: 這邊我們第一次用到了多核的方式來處理,一個CPU處理外部IO狀態造成的事件,一個CPU依據事件的發生來產生動作。大家也可以試試不用多核來寫會變成怎樣的寫法。

傳統程式架構 Get IO Process IO Check IO Event0 Active Get IO Process IO interrupt ISR Event1 Active 比較一下傳統的 MCU 程式設計方式。 Get IO Process IO Check IO Event2 Active

FPPA 觀點 Get IO Process IO Check IO Event0 Active Get IO Process IO interrupt ISR Get IO 以FPPA的觀點,程式可以讓妳自由的去分割到不同的CPU來執行,但是8個CPU仍舊是有限的,總不能讓無限制的來把程式分段放在不同的CPU來執行,系統一大起來,要處理的事情會變的非常的多,這個時候軟體的策略就很重要,怎樣去把不同的功能、不同的輸入、不同的輸出、重要性、優先程度、即時性…等等不同的系統需求來作整合、分配給不同的CPU使用,善用多核的優勢,才是FPPA程式設計的重要課題。 Process IO Check IO Event2 Active

系統規劃 硬體層 輸入控制 IO 處理 狀態控制 事件處理 主控程序 動作執行 硬體層 SOC 系統的規畫對一個專案的執行非常重要,整個系統其實就是一個狀態機,系統要求的功能抽象化出來,各個子系統可以獨立去設計、撰寫、維護程式,這對大型專案的開發非常有幫助,甚至可以讓多人協同開發一個大型專案變的相對容易。在軟體工程的定義上,便是資料層、邏輯層、表現層的分層規畫、設計,應用在韌體系統的開發上,其實是一樣的道理。 主控程序 動作執行 硬體層

MCU的軟體工程 輸入控制 UI 按鍵 IR/RF … 硬體IO層 LED 7-SEG Buzzer LCM UART … 輸出控制 狀態控制 自動控制 Sensor Timer … 寫程式的目的不光只是在把功能寫出來,還要考慮到可讀性(萬一需要由不同的人來作維護)、維護的方便性(bug維護)、功能增刪的便利性(軟硬體功能變更),習慣上,我把專案分成幾個不同的控制物件來撰寫程式,也就是模組化、物件化的概念,一個專案裡面事實上大致區分成這幾種控制,控制與控制之間是依據整個系統的狀態來達成協調。 不管是用FPPA、PIC、8051、ARM或甚至用PC來開發程式,這個概念是不變的。 大家可以參考軟體工程、多核多工或物件導向相關的書籍可以有更深入的了解。 底下再回到實作。 主控程序

第三周課程

事件觸發-多核的應用 eventLoop: t1sn EVENT0 call ActiveEvent0 t1sn EVENT1 … goto eventLoop ActiveEvent0: set1 TRIGGER0 ret ActiveEvent1: … ret … FPP-0 trigger0Loop: t1sn TRIGGER0 goto trigger0Loop set0 TRIGGER0 // TODO EVENT1 //TODO … 延伸上節的概念,同樣的,我們也可以把動作的程式碼分配給不同的核心來做,使用的技巧是透過一個FLAG旗標來作設定動作是不是被觸發,觸發時設成1,觸發後設成0,負責處理動作的CPU則是一直在等待觸發絛件成立,然後執行觸發的動作。 FPP-1 FPP-2 FPP-N 程式碼: 4FPPA程式設計-1-8&9多核的應用-蜂鳴器.asm

程式架構 FPP2 FPP1 FPP0 FPP Check Event0 Event0 Active Process Button Get Event0 Triggered Check Event0 Event0 Active Process Button Get Event0 Check Event1 FPP Event1 Triggered Check Event2 Get Event1 Event1 Active FPP Check Event3 Event2 Active Process IR Get Event2 Event3 Active 程式的架講看起來像這樣,當然,你可以依系統需求來調整哪些動作需要用這樣的方式來觸發。 哪些? 一些不希望被干擾的動作、或反過來不希影響主程序的工作、需要長時間去執行的動作…都適合拿來用這樣子的模式觸發。 底下舉蜂鳴器來作範例。 Get Event3

實作:多核的應用-蜂鳴器 mov a, BZ0_TIME; mov bz0_delay, a; BZ0DelayLoop: set1 BZ0; .repeat 1; delay BZ0_DUTY; set0 BZ0; .repeat 9; dzsn bz0_delay; goto BZ0DelayLoop; BZ0_DUTY 影響嗶聲頻率 Repeat 影響佔空比 BZ0_TIME 影響聲音持續時間 BZ0_DUTY x 1 重點講解,buzzer 發聲原理。 多核的應用蜂鳴器demo。 沒有用多核的話會如何? 程式不如預期~發生幾種狀況 一、按住的情況 二、放開的情況 三、連按的情怳 什麼原因? 怎麼解決? BZ0_DUTY x 9 370us, F = 2.7KHZ BZ0_DUTY x10 x BZ0_TIME

事件觸發-觸發條件控制 eventLoop: t0sn EVENT0 call ActiveEvent0 t0sn EVENT1 … goto eventLoop ActiveEvent0: t0sn EVENT_LOCK0 ret set1 EVENT_LOCK0 // TODO0 ActiveEvent1: set0 EVENT_LOCK0 // TODO1 ret 如同按鍵防彈跳的處理方式一樣,我們也可以設立旗標來限定某些事件在某些狀況下允不允許執行。同樣的也是用FALG來作設置,在事件被鎖住時設成1,解除時設成0。 Demo 2個蜂嗚器,解決按住的問題。 程式碼:4FPPA程式設計-1-10單一事件觸發.asm

多核的應用-CPU控制 Pause CPU Resume CPU ActiveEvent2: set1 LED1; set1 BZ1_CPU; ret; ActiveEvent3: set0 LED1; set0 BZ1_CPU; Pause CPU Resume CPU FPP-0 set0 BZ1_CPU; BZ1Loop: set1 BZ1; .repeat 9 delay BZ1_DUTY; set0 BZ1; .repeat 1; goto BZ1Loop; 隨時可以停止,控制一段程序的運行開始、停止的方法。 Demo 蜂嗚器 CPU 控制,解決放開的問題。 CPU停止的時機,主動或被動的方式? BZ1_CPU 程式碼:4FPPA程式設計-1-9單一事件觸發.asm

實作:多核的應用-CPU控制

Restart Program Counter 多核的應用-PC控制 ActiveEvent0: mov a, ha@RestartBZ0Loop; mov hb@tmpPC, a; mov a, la@RestartBZ0Loop; mov lb@tmpPC, a; pushw tmpPC; popw BZ0_PC; ret; Waitting for start goto $; RestartBZ0Loop: mov a, BZ0_TIME; mov bz0_delay, a; BZ0DelayLoop: set1 BZ0; .repeat 9 delay BZ0_DUTY; set0 BZ0; .repeat 1; dzsn bz0_delay; goto BZ0DelayLoop; FPP-0 Restart Program Counter 讓一段程序的重新運行的方法。 注意:要小心 STACK 的回復。 Demo 蜂嗚器 PC 控制,解決連按時的問題。 Waitting for restart BZ0_CPU

程式架構 FPP2 FPP1 FPP0 FPP Event0 Active Check Event0 Process Button Get START Event0 Active Check Event0 STOP Process Button Get Event0 Check Event1 FPP RESTART Event1 Active Check Event2 Get Event1 FPP Check Event3 Event2 Active Process IR Get Event2 Event3 Active IO 有支援 wait0 wait1 指令 RAM 沒有 Get Event3

實作:多核的應用-PC控制 ROM位址 行數 指令碼 Label標籤,虛指令 不佔指令碼 。 334 ||FPP3MainLoop: 335 || 336 0044 c044 || goto $; 337 ||RestartBZ0Loop: 338 0045 1ffa || mov a, BZ0_TIME; 339 0046 5c06 || mov bz0_delay, a; 420 007e 1f00 || mov a, ha@RestartBZ0Loop; 421 007f 5c01 || mov hb@tmpPC, a; 422 0080 1f45 || mov a, la@RestartBZ0Loop; 423 0081 5c00 || mov lb@tmpPC, a; 424 0082 0401 || pushw tmpPC; 425 0083 0063 || popw BZ0_PC; Compiler 在編譯時就會去查找Label所代表的位址。 重點講解,透過Lst 檔解析了解,FPPA在實際編譯成指令碼時的狀況,其實只是 ROM address 的 mov 同樣的用法可以用在取表指令 ldtabl 、 ldtabh tmpPC 00 45 word

系統規劃 IO 定義 輸入控制 IO 處理 事件處理 狀態控制 事件觸發 動作觸發 主控程序 動作執行 再回過頭來看之前的程式規劃,可以細分成這些個步驟。 動作觸發 主控程序 動作執行

蜂鳴器更多的應用方式 單音、連續二聲、長音、一連串的旋律…各種不同的音效。 BZ-FPP PLAY Sound Effect #1 Other-FPP Other-FPP Other-FPP PLAY Sound Effect #2 PLAY Sound Effect #3 PLAY Sound Effect #4 單音、連續二聲、長音、一連串的旋律…各種不同的音效。

各種不同的按鍵方式 按一下執行 按完放開執行 按住連續執行 按住一段時間後執行 連按二次後執行 組合鍵 一個按鍵的重作可以有很多不同操作的方法,按一下、按住、連按二下,按住3秒…

TIMER

自動控制-timer-循序 timerLoop: call Delay2sec // TODO goto timerLoop TIMER 計時器,主要的功用在系統定時,讓系統在固定時間會去執行某些程式,而在實際應用上可以分成兩大類,一、短時間的計時,二、長時間的計時。一般而言短時間的計時要求都是非常的精確到us,例如高速 PWM 輸出,這個我們可以用簡單的 delay 指令來達成,在往後的實習單元我們會用實例來介紹。而長時間的計時又分成二種,一種是要求不精準的,主要目的只是拿來分時執行不同的工作,另一種則正要求精確的長時間計時,譬如鬧鐘。其實基本的概念是相同的。 在實作上反而是長時間的計時比較麻煩也比較需要技巧,也就是這一章節主要要談的內容。 Todo的執行時間會影響到整個loop的總計時間,誤差會累積,並且難以控制。 如果有二件事要計時,要怎麼處理?

程式架構 MCU MCU Delay 2 sec Delay 1 sec TODO TODO0 Delay 2 sec TODO0 這是最直觀的作法,但是實際應用上會出問題,如果同時有好幾件工作要計時或有新的工作要加進來,時間就會變的難以估算。

自動控制-timer-TimeBased clear timer0_counter clear timer1_counter timerLoop: call Delay1s inc timer0_counter ceqsn timer0_counter, 1 goto noTimer0 // TODO0 noTimer0: inc timer1_counter ceqsn timer1_counter, 2 goto noTimer1 // TODO1 noTimer1: goto timerLoop 解決的方法是使用 time_base counter 的辦法,計算出系統所需 timer 的最小公因數,作為固定延時的基數,透過計數才達到不同時間計時的目的。

程式架構 MCU Delay base time Check Counter 0 TODO0 Check Counter 1 TODO1 同樣的Todo的執行時間會影響到整個loop的總計時間,誤差會累積,並且難以控制。 一般的專案這樣子的計時方式其實就己經足夠了,如果不是很CARE誤差,冬是要抓個大約的時間,間隔著去作,例如閃爍燈的功能。 但如果要更精確的計時?

自動控制-timer-事件處理 clear timer0_counter clear timer1_counter timerLoop: call Delay1s inc timer0_counter ceqsn timer0_counter, 1 goto noTimer0 set1 TIMER0 noTimer0: inc timer1_counter ceqsn timer1_counter, 2 goto noTimer1 set1 TIMER1 noTimer1: goto timerLoop GetEventLoop: clear SET_EVENT t0sn BUTTON0 set1 SET_EVENT0 t1sn BUTTON0 set1 SET_EVENT1 … t0sn TIMER0 t0sn TIMER1 set1 SET_EVNET1 mov a, SET_EVENT mov EVENT, a goto GetEventLoop 解答:在傳統的 MCU 解決的方式是使用 TIMER 中斷,FPPA一樣也有 TIMER 中斷,我們後面再來介紹,先來看看,不用中斷,用FPPA多核的特性如何來解決? 使用上一章提到的事件觸發的技巧,由一個 cpu 負責計時,在時間到了的時候發起一個事件,或直接 trigger 另一個 cpu 工作。 如此,todo的執行時間並不會會影響到整個loop的總計時間,誤差較容易控制,甚至可以修正到0誤差。 FPP-1 FPP-0

程式架構 TIMER HANDLE Delay base time Check Counter 0 Check Counter 1 CPU0 TODO0 TODO1 Check Counter 0 跟 Check Counter 0 的時間相較於長時間的計時的話是非常的短的。

程式架構 FPP2 FPP1 FPP0 FPP Check Event0 Event0 Active Process Button Get Event0 Triggered Check Event0 Event0 Active Process Button Get Event0 Check Event1 FPP Event1 Triggered Check Event2 Get Event1 Event1 Active FPP3 Check Event3 Event2 Active Process Timer Get Event2 Event3 Active Get Event3

自動控制-timer-動作觸發 clear timer0_counter clear timer1_counter timerLoop: call Delay1s inc timer0_counter ceqsn timer0_counter, 1 goto noTimer0 set1 TRIGGER0 noTimer0: inc timer1_counter ceqsn timer1_counter, 2 goto noTimer1 set1 TRIGGER1 noTimer1: goto timerLoop trigger0Loop: t1sn TRIGGER0 goto trigger0Loop set0 TRIGGER0 clear trigger0_counter // TODO0 FPP-1 trigger1Loop: t1sn TRIGGER1 goto trigger1Loop set0 TRIGGER1 clear trigger1_counter // TODO1 todo的執行時間並不會會影響到整個loop的總計時間,誤差較容易控制。 FPP-2 FPP-0

系統規劃 自動控制 TIMER 事件處理 狀態控制 事件觸發 動作觸發 主控程序 動作執行

消除時序上誤差的方法 A B clear timer0_counter timerLoop: delay 199 // 200us inc timer0_counter // +1 ceqsn timer0_counter, 1 // +1 goto noTimer0 // +1 clear timer0_counter // +1 set1 TIMER0 // +1 noTimer0: goto timerLoop // +1 1us 常數 202us 常數 ? 條件判斷式 1us 2us A B 變數 205us or 204us ? 1us 常數 先討論為何會產生誤差,主要有二,一是因為程式運行本身需要時間,這個比較好修正,只要更改固定delay的時間即可,二是程式遇到的分岐造成延時不固定,在這裡 A 跟 B 就會有 1us 的誤差產生。 消除誤差的技巧不止在這裡用的到,其它很需要精確計算時序的應用也常常會用到。

消除時序上誤差的方法 A B clear timer0_counter timerLoop: delay 199 // 200us inc timer0_counter // +1 ceqsn timer0_counter, 1 // +1 goto noTimer0 // +1 goto isTimer0 // +1 isTimer0: clear timer0_counter // +1 set1 TIMER0 // +1 goto endTimer0 // +1 noTimer0: nop // +1 endTimer0: goto timerLoop // +1 1us 常數 202us 常數 ? 條件判斷式 4us 4us A B 常數 1us 常數 方法很簡單,就是讓不同的分岐都跑相同的時間,也就是透過加空指令 nop 來調整時序,把變數都變成常數,如此一來要調整整個工作的時序就變的非常簡單了,只要改變常數就可以了,這個技巧在要求短時間且精確的時序控制上是非常有用的。 這樣程式看起來比較多,但卻比較具可讀性,而且確實的指定程式的走向,是比較方便維護的,不會因為程式碼增加淢少造成潛藏的bug。 207us

自動控制-timer-使用內部timer Initial_ISR: mov a, 0b00000000; mov intrq, a; /// clear interrpt reqest register mov a, 0b00000100; mov inten, a; /// initial interrupt 0=Disable 1=Enable engint; /// Enable Interrupt intrq & inten: /// Bit Description bit-0: PA.0 bit-1: PA.1 bit-2: Timer16 bit-3: General 0 bit-4: General 1 bit-5: General 2 bit-6: General 3 bit-7: General 4 FPP0 Interrupt Subroutine intrq!=0 另解決方式是使用系統提供的 16bit timer,接下來介紹它的基本使用方法。 FPPA 的中斷暫存器介紹 FPPA 負責處理中斷的CPU FPP0 FPPA 中斷運作的方式 Interrupt Subroutine intrq!=0 intrq!=0 Interrupt Subroutine

engint & inten intrq Interrupt 運作示意圖 user define time’s up toggled .romadr 0x010 FPP0 ISR engint & inten 7 6 5 4 3 2 1 intrq 7 6 5 4 3 2 1 General Timer PA1 PA0 user define time’s up toggled toggled 當 intrq.n=1 而且 inten.n=1 時,FPP0 會自動進入ISR,也就是程式碼 0X010 的位址。(*會用掉 2bytes stack ) 程式設計時必須負責作好狀態保存(有可能干擾FPP0的變數),在處理完中斷後須要將 intrq.n 重設為 0 並且作狀態回復。

自動控制-timer-使用內部timer Initial_TIMER: mov a, 0b10011111; /// 使用內部 OSC - 16MHZ mov t16m, a; mov a, 0x1E; mov hb@t16reset, a; mov a, 0x58; mov lb@t16reset, a; stt16 t16reset; /// Restart timer tick t16m: /// Bit Description Timer Clock Source = 7 ~ 5  000:NONE 001:SYS 100:IHRC 101:OSC 110:ILRC 111:PA0 Timer Clock Prescale = 4 ~ 3  00:Clock/1 01:Clock/4 10:Clock/16 11:Clock/64 Interrupt sorce = 2 ~ 0  000:bit8 ~ 111:bit15 carrayinterrupt InterrupTime = ClockSource/Prescale*Counter, Counter is base on sorce ie. 想要產生每 100000us 一次的中斷  OSC=16MHz, Prescale=1/64, 1-tick = 64/16 = 4us  count#=100000/4=25000, Sorce = 111(32768), stt16=32768-25000=0x1E58 FPPA TIMER 使用的暫存器介紹 使用 pa0 可以當作計數器

Timer 運作示意圖 engint & inten 7 6 5 4 3 2 1 intrq 7 6 5 4 3 2 1 Score t16 intrq 7 6 5 4 3 2 1 Score t16 16384 4096 1024 256 32768 8192 2048 512 /Prescale Clock Source 7 6 5 4 3 2 1 t16m OSC PA0

自動控制-timer-使用內部timer .romadr 0x0010 Interrupt: set0 intrq.2; /// clear interrpt reqest register stt16 t16reset ; /// Restart timer tick inc timer0_counter; mov a, timer0_counter; ceqsn a, 10; /// = 100000us*10=1sec goto noTimer0; clear timer0_counter; // TODO0 /// set trigger or event noTimer0: inc timer1_counter; mov a, timer1_counter; ceqsn a, 20; /// = 100000us*20=2sec goto noTimer1; clear timer1_counter; noTimer1: reti; todo的執行時間並不會會影響到整個loop的總計時間,誤差不會累積,並且可以控制,甚至修正到零誤差。 (前提是todo的時間少於所給予的時間片段。 如果是透過事件驅動的方式,更是能夠準確的控時計時。

自動控制-timer-使用內部timer-自行處理中斷 disgint; ISRLoop: t1sn intrq.2; goto ISRLoop; set0 intrq.2; /// clear interrpt reqest register stt16 t16reset ; /// Restart timer tick inc timer0_counter; mov a, timer0_counter; ceqsn a, 10; goto noTimer0; clear timer0_counter; // TODO0 /// set trigger or event noTimer0: inc timer1_counter; mov a, timer1_counter; ceqsn a, 20; goto noTimer1; clear timer1_counter; noTimer1: T16M 設定好後,不論有無啟用中斷均會開始累加,並且在進位時觸發 intrq,也就是說可以透過觀察intrq來看看是否有中斷請求發生(timer進位、pa0、pa1改變準位…),因此可以由別的CPU來處理中斷~而不打擾到FPP0的運行。

程式架構 TIMER TIMER HANDLE timer Check Counter 0 Check Counter 1 CPU0 TODO0 TODO1 總結使用 TIMER 跟不使用 TIMER 的差別… 使用 TIMER 就像透過一個獨立計時裝置來計時, 如果TIIMER HANDLE 的處理時間小於 timer 的計時時間,則誤差是可以自動修正回來的,因此可以保證誤零誤差。 而使用自己計時的話,則要自己去計算,修正誤差,同樣的,也是能調整到零誤差,以結果而言,其實是一樣的,只是技巧不同。

傳統程式架構 Get IO Process IO Check IO Event0 Active Get IO Process IO interrupt ISR Event1 Active 傳統的 MCU 程式設計。 Get IO Process IO Check IO Event2 Active

I O EVENT 多核程式架構 FPP2 FPP1 FPP0 FPP Check Event0 Event0 Active Process Event0 Triggered Check Event0 Event0 Active Process Button Get Event0 Check Event1 FPP Event1 Triggered Check Event2 Get Event1 Event1 Active FPP3 Check Event3 Event2 Active Process Timer Get Event2 傳統的 MCU 的系統規畫只是概念上的抽象,到了真正實作還是得乖乖的循序去作,細節的處理跟實現都需要程式設計師去完成,多核的系統不止是概念上,連實作上都可以達到硬體層、邏輯層、表現層不同的縱向規畫。 Event3 Active Get Event3