2016年3月24日 星期四

微處理器實作: AT89S52 程式練習(多重中斷)

        這個練習在於練習同時使用多個中斷服務: 兩個內部計數器(timer0, timer1)和兩個外部中斷(按鍵P3.2和P3.3)。timer0 控制變數mynum,每秒加1,timer1 控制變數mynum_2,每0.5秒加1,按鍵P3.2 按下時,將mynum_2歸0,按鍵P3.3 按下時,將mynum歸0。


執行結果:



完整程式碼如下:

#include <regx52.h>

#define LED_NUM_0 0xC0
#define LED_NUM_1 0xF9
#define LED_NUM_2 0xA4
#define LED_NUM_3 0xB0
#define LED_NUM_4 0x99
#define LED_NUM_5 0x92
#define LED_NUM_6 0x82
#define LED_NUM_7 0xF8
#define LED_NUM_8 0x80
#define LED_NUM_9 0x98

#define LED_OUT P1

int count   = 1024;
int count_2 = 1024;
int mynum = 0;
int mynum_2 = 0;

unsigned char led_num[10] =
{
LED_NUM_0, LED_NUM_1, LED_NUM_2, LED_NUM_3, LED_NUM_4, 
LED_NUM_5, LED_NUM_6, LED_NUM_7, LED_NUM_8, LED_NUM_9
};

void my_delay(unsigned int n)
{
unsigned int i, j;

for(j=0; j<n; j++)
for(i=0; i<120; i++) ; 

}

void T0_int(void) interrupt 1
{
TL0 = (65535-1024*12) % 256;
TH0 = (65535-1024*12) / 256;

if(count ==0 )
{
count=1024; // 1024*1204*12 => 1 second
mynum++;
if (mynum == 10) mynum = 0;

}
else 
           count--;
}

void T1_int(void) interrupt 3
{
TL1 = (65536-1024*6) % 256;
TH1 = (65536-1024*6) / 256;

if(count_2 ==0 )
{
count_2=1024; // 1024*1204*12 => 1 second
mynum_2++;
if (mynum_2 == 10) mynum_2 = 0;

}
else 
count_2--;
}

void EX0_int(void) interrupt 0
{
mynum_2 = 0;
}

void EX1_int(void) interrupt 2
{
mynum = 0;
}

main()
{

TMOD = 0x00;                  // set timer control register
TL0 = (65536-1024*12) % 256;  // set count number:12K for 1/1024 sec
TH0 = (65536-1024*12) / 256;  // set count number:12K(TH  1/1024 sec
TL1 = (65536-1024*6)  % 256;  // set count number: 6K(TL  1/2048 sec
TH1 = (65536-1024*6)  / 256;  // set count number: 6K(TL  1/2048 sec

ET0 =1; ET1 = 1; EX0 = 1; EX1 = 1; EA =1; //set IE register
TR0 =1; TR1 = 1; IT0 = 1; IT1 = 1;        //set TCON register      
P3_4 = 0; //pull low p3.4 for enable EX0 and EX1

while(1)
{
   P3_0 = 0; P3_1 =1;
   LED_OUT = led_num[mynum];
   my_delay(3);
   LED_OUT = 0xFF;  
  
          P3_0 = 1; P3_1 =0;
 LED_OUT = led_num[mynum_2];
  my_delay(3);
  LED_OUT = 0xFF;
}
}

2016年3月23日 星期三

微處理器實作: AT89S52 程式練習(計數器中斷)

        這個程式主要練習設定AT89S52的中斷並啟動,另外還要設計中斷服務程式ISR,當中斷發生時最對應的動作: 主程式先設定timer 0的中斷並啟動,然後就進入無窮迴圈(顯示mynum的值),而timer 0數到12*1024(1ms)時,即發出一個中斷,此時count 減 1,如此經過1024次之後(1秒),mynum加1,這就是一個最簡單的計時器了(以秒為單位)。


執行結果

以下為完整程式碼:

#include <REGX52.h>

#define LED_NUM_0 0xC0
#define LED_NUM_1 0xF9
#define LED_NUM_2 0xA4
#define LED_NUM_3 0xB0
#define LED_NUM_4 0x99
#define LED_NUM_5 0x92
#define LED_NUM_6 0x82
#define LED_NUM_7 0xF8
#define LED_NUM_8 0x80
#define LED_NUM_9 0x98

#define LED_OUT P1

int count = 1024;
int mynum = 0;

unsigned char led_num[10] =
{
LED_NUM_0, LED_NUM_1, LED_NUM_2, LED_NUM_3, LED_NUM_4, 
LED_NUM_5, LED_NUM_6, LED_NUM_7, LED_NUM_8, LED_NUM_9
};

void my_delay(unsigned int n)
{
unsigned int i, j;

for(j=0; j<n; j++)
for(i=0; i<120; i++) ; 

}

void led_write_1c(unsigned char r, unsigned char x)
{
P3 = ~(1 << (3-r)); //enable control bit: active LOW
LED_OUT = x;
my_delay(3);
LED_OUT = 0xFF;
} 

void led_write_1c_nc(unsigned char r, unsigned char x)
{
P3 = ~(1 << (3-r)); //enable control bit: active LOW
LED_OUT = x;
my_delay(3);
//LED_OUT = 0xFF;
} 

void led_write_4c(unsigned short x)
{
led_write_1c(0, led_num[x%10    ]);
led_write_1c(1, led_num[x/10%10 ]);
led_write_1c(2, led_num[x/100%10]);
led_write_1c(3, led_num[x/1000  ]);
} 

void T0_int(void) interrupt 1
{
TL0 = (65535-1024*12) % 256;
TH0 = (65535-1024*12) / 256;

if(count ==0 )
{
count=1024; // 1024*1204*12 => 1 second
mynum++;
}
else 
count--;
}

main()
{
TMOD = 0x00;                                // set timer control register
TL0 = (65535-1024*12) % 256;     // set count number:12K(TL of timer 0)
TH0 = (65535-1024*12) / 256;      // set count number:12K(TH of timer 0)
IE = 0x82;                                       // set interrupt enable register 
TR0 = 1;                                         // enable timer 0
while(1)
{
led_write_4c(mynum);
}
}

微處理器實作: 音樂鬧鐘PCB Layout

        以Atmel公司的AT89S52微處理器為基礎,設計一個PCB版,焊上電子元件之後,在上面開發對應之軟體。

用Altium Designer 繪製的電路圖(Schematic)


PCB Layout (佈線圖)

曝光


顯影


顯影完成的PCB


蝕刻


蝕刻完成的PCB



焊上元件的成品

成品背面



2016年3月21日 星期一

LabVIEW: 猜燈號遊戲

設計8個LED燈號,使其從A0到A7依序閃爍,其中練習Shift Register的回饋機制,另外在利用Conditional Terminal 的功能,及時停止迴圈進行,最後比較使用者的輸入和燈號是否符合,並選擇是否繼續遊戲。





影片連結:
https://www.youtube.com/watch?v=bQGng5TuVnw&feature=youtu.be






LabVIEW: Flat Sequence 結構 和 Case 結構

          Flat Sequence 結構,顧名思義就是循序動作的集合,像是底片播放一樣,一張一張依序執行。這個練習是利用Flat Sequence 結構的順序性,讓三個LED燈依序亮起。



Case 結構和C語言的Switch-Case很像,輸入是什麼值,就做對應的動作,以下練習是改寫上面三個LED燈依序亮起的程序,所以Case 結構是可以取代上面 Flat Sequence Structure的。

輸入是0 就亮led 0,1 就亮 led 1,2 就亮 led 2,記住: 所有case都要填入對應動作,否則程式無法執行(斷鍊)。



LabVIEW: 迴圈練習

         迴圈是程式中不可或缺的部分,在LabVIEW裡,迴圈的設置很間單也很直覺,以for loop來說,只要設定迴圈次數N,就可以運作了,很方便,再搭配計數器 i ,更可以組合出多種變化,while迴圈則是要注意判斷執行及停止條件,也很容易。

在for 迴圈內用一亂數產生器,產生10次亂數並把結果輸出至Waveform Chart。


輸出結果,要注意i的範圍是從0到9,並非1到10。


換成While迴圈,while迴圈停止的條件有Stop if true 和 Continue if true兩個版本,要注意使用時機。

Continue if true 版本的while 迴圈,注意判斷條件。


輸出結果: 取10次亂數產生的結果。


幾個英語學習網站

1. VOA 新聞網 : http://learningenglish.voanews.com/ 英語新聞網站,有文字稿,可以交相對照。
2. 英語學習網 http://www.esl-lab.com/ ,有測驗題目,可以驗收聽力訓練的成果。
3. TED 分享網 http://www.ted.com/
4. TED ED http://ed.ted.com/

Quartus: 自動骰子機(1)

            這個練習的主要目的在於供給一個穩定頻率的方波(Pin43),再透過7490計數器產生三個輸入,再供給骰子電路,並依輸入值輸出對應LED的燈號。


Block Diagram/Schematic 線路圖


CPLD 腳位配置 (Pin Assignment)


模擬(Simulation)結果




實際執行結果

2016年3月20日 星期日

C# : 建構多重文件介面(MDI) 視窗

         建構多重文件介面(MDI) 視窗是開發視窗軟體的基本步驟,本練習的重點在於實作一個基本的多重文件介面(MDI) 視窗結構。

步驟1:
把主視窗Form1的屬性IsMdiContainer設為True。



步驟2: 
從工具箱找出MenuStrip元件,並拖曳至Form1



步驟3:
在"在這裡輸入"空白處依序輸入檔案(&F)和編輯(&E)


步驟4:
點選檔案(F),在其下方加入兩個子項,開啟(O)和離開(X),並將其ShortcutKeys屬性分別改成,Ctrl+O和Ctrl+X



步驟5:
從工具箱找出對話方塊內的OpenFileDialog元件,拖曳至Form1內。
並將其Filter屬性填入JPEG檔案(*.jpg)|*.jpg|PNG檔案(*.png)|*.png
FileName屬性清空。


步驟5:
選擇專案->加入WindowsForm 選擇 WindowsForm (Form2)。y再從工具箱找出PictureBox元件,拖曳至Form2內。並按下PictureBox邊緣的小箭頭,點選停駐於父容器中。此時PictureBox會附著於Form2內。


步驟六: 
將Form2.Designer.cs檔案內的
private System.Windows.Forms.PictureBox pictureBox1;
改成
public System.Windows.Forms.PictureBox pictureBox1;

Form1.cs檔案內加入程式碼(藍色文字部分): 
       private void Menu_File_Open_Click(object sender, EventArgs e)
        {
           if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Form2 frm = new Form2();
                frm.MdiParent = this;
                frm.Show();
                frm.WindowState = FormWindowState.Maximized;
                frm.pictureBox1.Load(openFileDialog1.FileName);
                frm.Text = openFileDialog1.FileName;
            }
        }




這樣就完成了一個簡易的秀圖程式了......







C# : 建立視窗和元件,修改屬性,數字和字串轉換

        C#基本上上是視覺化的程式語言,和Visual Basic很像,只是它繼承了C++的語法,用C#來開發視窗程式很直覺,也很方便。
        
        這個程式主要是練習C#元件的基本操作: 建立3個文字方塊,5個按鍵,作兩個數字的四則運算。其中比較值得注意的是Error Handling的部分(紅色文字),在使用者輸入錯誤時,可以攔截並做對應處理,防止程式和系統錯亂。另外,this指的是成本身,所以this.Close(); 就是關閉程式,Double.Parse() 是用來將字串轉成數字,ToString()  是把數字轉成字串,以方便文字方塊顯示。

       


視窗畫面



底下是程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace P20160314_2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void btnAdd_Click(object sender, EventArgs e)
        {
            Double r;
            try
            {
                r = Double.Parse(txtNum1.Text) + Double.Parse(txtNum2.Text);
                txtResult.Text = r.ToString();
            }
            catch (Exception err)
            {
                MessageBox.Show("Wrong Input!!!");
                txtNum1.Text = "";
                txtNum2.Text = "";
                txtResult.Text = "";
            };
        }

        private void btnSub_Click(object sender, EventArgs e)
        {
            Double r;
         
            try
            {
                r = Double.Parse(txtNum1.Text) - Double.Parse(txtNum2.Text);
                txtResult.Text = r.ToString();
            }
            catch (Exception err)
            {
                MessageBox.Show("Wrong Input!!!");
                txtNum1.Text = "";
                txtNum2.Text = "";
                txtResult.Text = "";
            };
        }

        private void btnMul_Click(object sender, EventArgs e)
        {
            Double r;

            try
            {
                r = Double.Parse(txtNum1.Text) * Double.Parse(txtNum2.Text);
                txtResult.Text = r.ToString();
            }
            catch (Exception err)
            {
                MessageBox.Show("Wrong Input!!!");
                txtNum1.Text = "";
                txtNum2.Text = "";
                txtResult.Text = "";
            };
        }

        private void btnDiv_Click(object sender, EventArgs e)
        {
            Double r;

            try
            {
                r = Double.Parse(txtNum1.Text) / Double.Parse(txtNum2.Text);
                txtResult.Text = r.ToString();
            }
            catch (Exception err)
            {
                MessageBox.Show("Wrong Input!!!");
                txtNum1.Text = "";
                txtNum2.Text = "";
                txtResult.Text = "";
            };
        }
    }
}

LabVIEW: 七段顯示器Demo程式播放器

        在上一篇中,用LabVIEW做了一個七段顯示器Demo程式編輯器 (LabVIEW: 七段顯示器Demo程式編輯器),朋友看了覺得很不錯,於是建議我再做一個播放器,看看編輯出來的結果是否正確。我覺得這個建議很棒,也可以拿來當成練習,於是花了一些時間把它實作出來,過程有遇到一些困難,但是上網查資料之後,很快就解決了。

        用LabVIEW寫程式實在是蠻有樂趣的,像極了用LEGO積木堆積出你要的工具 ^_^,以下就是我的程式部分:


方塊圖


人機介面



播放器執行的情況,不用放到實際硬體上,在PC上就可以知道執行結果,等到最後編修完成,再放到硬體上就可以了,非常方便,也很節省開發時間。




LabVIEW: 七段顯示器Demo程式編輯器

       根據之前文章 四合一7段顯示器(共陽極)的demo程式 中,七段顯示器中的動畫是由591個畫面所構成,如果每個畫面保守估計要花一分鐘的話,那麼這段動畫就要花上10個小時左右(而且還不能出錯),當然,有更聰明的做法,那就是設計一個編輯器良製作這些動畫,而且要操作容易,直覺,於是,我想到了用LabVIEW的人機介面,設計了這個編輯器,操作非常容易,七段顯示器的動畫一下子就可以完成,非常輕鬆愉快。








程式執行結果如下: 這樣編輯動畫是不是輕鬆多了~~~~~~~  ^_^


編輯出來的結果會是如下的結構,
{顯示器3的編碼, 顯示器2的編碼, 顯示器1的編碼,顯示器0的編碼,顯示時間},
然後再把這些資料未給Arduino的播放程式,就可以產生很豐富的動畫了。


{ 255, 255, 255, 255, 10 },
{ 254, 255, 255, 255, 10 },
{ 254, 254, 255, 255, 10 },
{ 254, 254, 254, 255, 10 },
{ 254, 254, 254, 254, 10 },
{ 254, 254, 254, 252, 10 },
{ 254, 254, 254, 188, 10 },
{ 254, 254, 190, 188, 10 },
{ 254, 190, 190, 188, 10 },
{ 190, 190, 190, 188, 10 },
{ 174, 190, 190, 188, 10 },
{ 166, 190, 190, 188, 10 },
{ 166, 182, 190, 188, 10 },
{ 166, 182, 182, 188, 10 },
{ 166, 182, 182, 180, 10 },
{ 166, 182, 182, 188, 10 },
{ 166, 182, 190, 188, 10 },
{ 166, 190, 190, 188, 10 },
{ 174, 190, 190, 188, 10 },
{ 190, 190, 190, 188, 10 },
{ 254, 190, 190, 188, 10 },
{ 254, 254, 190, 188, 10 },
{ 254, 254, 254, 188, 10 },
{ 254, 254, 254, 252, 10 },
{ 254, 254, 254, 254, 10 },
{ 254, 254, 254, 255, 10 },
{ 254, 254, 255, 255, 10 },
{ 254, 255, 255, 255, 10 },
.
.
.
.
.
.

2016年3月15日 星期二

LabVIEW: Cluster 叢集基本操作

         在LabVIEW裡的叢集,指的是一些不同類型物件的集合,不同於Array陣列中,都必須是同一類型的物件。本練習建構一個叢集,其中包含四個物件,之後從這個叢集中取出(unbundle)兩個物件,在進行重組(bundle)一個新叢集。




LabVIEW: 取二維陣列中的元素

這個練習很單純:建構一個布林二維陣列,再取其中Array[2][6]的元素,輸出其值。






2016年3月14日 星期一

LabVIEW: Array 陣列的基本操作

這個練習的重點在於建構一個數值陣列,其中包含10個元素,值分別是1,2,3,4,5,6,7,8,9,10,然後利用元件找出陣列大小,和索引(index)為5的數值,最後再取出從A[5]開始的4個值,取平均值。





LabVIEW: 現值範圍及合成字串輸出練習

這個練習是先用一個旋鈕元件輸出1~100之間的數值,再用限制範圍元件將其值的範圍設為20~40,然後再判斷是否超出範圍並將結果輸出。




LabVIEW: 字串和數字間的轉換練習

       這個練習是從固定格式的輸入字串中(五位數小數前後前後各夾雜一個#字號),將數字字串取出,再轉成數字格式輸出給儀表顯示,之後再將這個數字加上255之後再轉成字串並輸出。





這個練習中會用到三個新元件,

"String Subset": 取部分字串,可指定起始位置(offset)和長度(length)

"Fract/Exp String to Number": 字串轉數字,包含小數和e指數

"Number to Fractional String": 數字轉字串,可限定長度和精確度