# 介面lab02
##### 助教疑問
- 用邏輯分析儀測量訊號
- 說明TWI 另外名稱是什麼?原理?
- 另外名稱:I²C,之所以改名為 Two Wire Interface (TWI) 是為了規避 I2C Bus 專利
- 原理:透過SDA、SCL線,讓掛在這兩條線上的主裝置及僕裝置能夠「逐一位元」進行資料讀寫交換。
- M128TWI Slave 同時能很多個嗎?
- (說明若可以是為什麼 不行又是為什麼)
- 可以,TWI通訊協定中有一主多僕通訊架構,以及位址解碼功能,總共提供128個位址給不同的僕裝置
- 你還有一顆IC TCA9534A 沒做?
- 已完成
- 告訴你現在bit rate傳送速率多少?
- 287.5Kbps
## 工作日誌
* 7/15開始閱讀講義
* 7/29複習中斷
* 8/3硬體配線完成
## 程式碼
#### TCA9534
### 1. TCA9534A輸出七節管
```c
#include "c4mlib.h"
#define F_CPU 11059200UL
int main()
{
C4M_DEVICE_set();
char SLA=56;//Slave(僕)裝置的TWI ID
char SevenSegTable[]={0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111};
//---TWI串列通訊埠旗標群設定REGFPT---//
REGFPT(&TWSR, 0x03, 0, 0);//設定TWI通訊工作時脈
REGFPT(&TWCR, 0x01, 0, 1);//致能TWI通訊
REGFPT(&TWCR, 0x04, 2, 1);//致能TWI中斷
REGFPT(&TWAR, 0xFE, 1, SLA);//設定TWI編號 依據接線設定地址ADD
REGFPT(&TWAR, 0x01, 0, 0);//選擇擴播關閉
REGFPT(&DDRD, 0x03, 0, 3);//檢察並設定TWI通訊接腳為輸出
//---TWI串列通訊埠暫存器設定REGPUT---//
REGPUT(&TWBR, 1, 12);//設定TWI通訊工作時脈 TWBR預設值12
//---設定TCA9534A暫存器參數TWIM_trm---//
TWIM_trm(5, SLA, 0x02, 1, 0b00000000, 10);//設定極性反轉設定
TWIM_trm(5, SLA, 0x03, 1, 0b00000000, 10);//設定輸出入方向設定
while (1)
{
for (int i=0;i<10;i++)
{
printf("i=%d\n",i);
TWIM_ftm(5, SLA, 0x01, 0xFF, 0, &SevenSegTable[i], 10);//輸出資料
_delay_ms(700);
}
}
}
```
### 2.TCA9534A輸入
```c
#include "c4mlib.h"
#define F_CPU 11059200UL
int main()
{
C4M_DEVICE_set();
char SLA=56;//Slave(僕)裝置的TWI ID
char InData;
//---TWI串列通訊埠旗標群設定REGFPT---//
REGFPT(&TWSR, 0x03, 0, 0);//設定TWI通訊工作時脈
REGFPT(&TWCR, 0x01, 0, 1);//致能TWI通訊
REGFPT(&TWCR, 0x04, 2, 1);//致能TWI中斷
REGFPT(&TWAR, 0xFE, 1, SLA);//設定TWI編號 依據接線設定地址ADD
REGFPT(&TWAR, 0x01, 0, 0);//選擇擴播關閉
REGFPT(&DDRD, 0x03, 0, 3);//檢察並設定TWI通訊接腳為輸出
//---TWI串列通訊埠暫存器設定REGPUT---//
REGPUT(&TWBR, 1, 12);//設定TWI通訊工作時脈 TWBR預設值12
//---設定TCA9534A暫存器參數TWIM_trm---//
TWIM_trm(5, SLA, 0x02, 1, 0b00000000, 10);//設定極性反轉設定
TWIM_trm(5, SLA, 0x03, 1, 0b00000000, 10);//設定輸出入方向設定
while (1)
{
for (int i=0;i<10;i++)
{
TWIM_frc(5, SLA, 0x00, 0xFF, 0, &InData, 10);
printf("InData=%d\n",InData);
_delay_ms(700);
}
}
}
```
#### TMP175
### 1. 休眠模式下單發量測溫度
```c
#include "c4mlib.h"
#define F_CPU 11059200UL
uint8_t temp[2];//廣域2位元組讀值變數
int main()
{
C4M_DEVICE_set();
char SLA=72;//Slave(僕)裝置的TWI ID
uint8_t Htemp[2]={30, 0};//高溫門檻設定[0]整數[1]小數
uint8_t Ltemp[2]={28, 0};//低溫門檻設定[0]整數[1]小數
uint8_t SD=0;//休眠模式設定旗標
uint8_t TM=0;//溫度量測模式設定旗標
uint8_t POL=1;//警告極性設定旗標(與TM旗標共同決定警告的波形)
uint8_t F1F0=1;//警告延遲設定選擇旗標群
uint8_t R1R0=0;//解析度設定選擇旗標群
uint8_t OS=1;//單發控制旗標
//---TWI串列通訊埠旗標群設定REGFPT---//
REGFPT(&TWSR, 0x03, 0, 0);//設定TWI通訊工作時脈
REGFPT(&TWCR, 0x01, 0, 1);//致能TWI通訊
REGFPT(&TWCR, 0x04, 2, 1);//致能TWI中斷
REGFPT(&TWAR, 0xFE, 1, SLA);//設定TWI編號 依據接線設定地址ADD
REGFPT(&TWAR, 0x01, 0, 0);//選擇擴播關閉
REGFPT(&DDRD, 0x03, 0, 3);//檢察並設定TWI通訊接腳為輸出
//---TWI串列通訊埠暫存器設定REGPUT---//
REGPUT(&TWBR, 1, 12);//設定TWI通訊工作時脈 TWBR預設值12
//---TMP175暫存器旗標群參數設定TWIM_ftm---//
TWIM_ftm(5, SLA, 0x01, 0x01, 0, &SD, 10);//設定休眠模式
TWIM_ftm(5, SLA, 0x01, 0x60, 5, &R1R0, 10);//設定量測解析度0.5度C 9bits
while (1)
{
TWIM_ftm(5, SLA, 0x01, 0x80, 7, &OS, 10);//設定單發模式量測溫度
TWIM_rec(5, SLA, 0, 2, temp, 10);//讀取溫度
printf("%d.%d C\n", temp[0], temp[1]*10/256);
_delay_ms(1000);
}
}
```
### 2. 比較模式下過溫度中斷警告
```c
#include "c4mlib.h"
#define F_CPU 11059200UL
uint8_t Interrupt=0;//中斷旗標
uint8_t temp[2];//廣域2位元組讀值變數
int main()
{
C4M_DEVICE_set();
char SLA=72;//Slave(僕)裝置的TWI ID
uint8_t Htemp[2]={30, 0};//高溫門檻設定[0]整數[1]小數
uint8_t Ltemp[2]={28, 0};//低溫門檻設定[0]整數[1]小數
uint8_t SD=0;//休眠模式設定旗標
uint8_t TM=0;//溫度量測模式設定旗標
uint8_t POL=1;//警告極性設定旗標(與TM旗標共同決定警告的波形)
uint8_t F1F0=1;//警告延遲設定選擇旗標群
uint8_t R1R0=0;//解析度設定選擇旗標群
uint8_t OS=0;//單發控制旗標
//---TWI串列通訊埠旗標群設定REGFPT---//
REGFPT(&TWSR, 0x03, 0, 0);//設定TWI通訊工作時脈
REGFPT(&TWCR, 0x01, 0, 1);//致能TWI通訊
REGFPT(&TWCR, 0x04, 2, 1);//致能TWI中斷
REGFPT(&TWAR, 0xFE, 1, SLA);//設定TWI編號 依據接線設定地址ADD
REGFPT(&TWAR, 0x01, 0, 0);//選擇擴播關閉
REGFPT(&DDRD, 0x03, 0, 3);//檢察並設定TWI通訊接腳為輸出
//---TWI串列通訊埠暫存器設定REGPUT---//
REGPUT(&TWBR, 1, 12);//設定TWI通訊工作時脈 TWBR預設值12
//---設定TMP175暫存器參數TWIM_trm---//
TWIM_trm(5, SLA, 0x02, 2, Ltemp, 10);//設定低溫門檻
TWIM_trm(5, SLA, 0x03, 2, Htemp, 10);//設定高溫門檻
TWIM_rec(5, SLA, 0x02, 2, Ltemp, 10);
TWIM_rec(5, SLA, 0x03, 2, Htemp, 10);
printf("Ltemp=%d C\n",Ltemp[0]);
printf("Htemp=%d C\n",Htemp[0]);
//---TMP175暫存器旗標群參數設定TWIM_ftm---//
TWIM_ftm(5, SLA, 0x01, 0x01, 0, &SD, 10);//設定休眠模式
TWIM_ftm(5, SLA, 0x01, 0x02, 1, &TM, 10);//設定溫度比較模式TM=0
TWIM_ftm(5, SLA, 0x01, 0x04, 2, &POL, 10);//設定Alert極性 POL HI
TWIM_ftm(5, SLA, 0x01, 0x18, 3, &F1F0, 10);//設定延遲次數2
TWIM_ftm(5, SLA, 0x01, 0x60, 5, &R1R0, 10);//設定量測解析度0.5度C 9bits
//----外部中斷硬體設定----//
REGFPT(&DDRE, 0x80, 7, 0);//設定外部中斷觸發源Port E7為輸入
REGFPT(&EICRB, 0xC0, 6, 3);//設定上緣觸發
REGFPT(&EIMSK, 0x80, 7, 1);//設定外部中斷致能
sei();//致能中斷
while (1)
{
TWIM_rec(5, SLA, 0, 2, temp, 10);//讀取溫度
printf("Current temperature is %d.%d C\n", temp[0], temp[1]*10/256);
if (Interrupt==1)
{
if (temp[0]<Htemp[0])
{
Interrupt=0;
}
}
_delay_ms(500);
}
}
ISR(INT7_vect)
{
Interrupt=1;
printf("High temperature alert\n");
}
```
### 3. 量測模式下固定週期量測並顯示
```c
#include "c4mlib.h"
#define F_CPU 11059200UL
uint8_t Interrupt=0;//中斷旗標
uint8_t temp[2];//廣域2位元組讀值變數
char SLA=72;//Slave(僕)裝置的TWI ID
int main()
{
C4M_DEVICE_set();
uint8_t Htemp[2]={30, 0};//高溫門檻設定[0]整數[1]小數
uint8_t Ltemp[2]={28, 0};//低溫門檻設定[0]整數[1]小數
uint8_t SD=0;//休眠模式設定旗標
uint8_t TM=1;//溫度量測模式設定旗標
uint8_t POL=1;//警告極性設定旗標(與TM旗標共同決定警告的波形)
uint8_t F1F0=1;//警告延遲設定選擇旗標群
uint8_t R1R0=0;//解析度設定選擇旗標群
uint8_t OS=0;//單發控制旗標
//---TWI串列通訊埠旗標群設定REGFPT---//
REGFPT(&TWSR, 0x03, 0, 0);//設定TWI通訊工作時脈
REGFPT(&TWCR, 0x01, 0, 1);//致能TWI通訊
REGFPT(&TWCR, 0x04, 2, 1);//致能TWI中斷
REGFPT(&TWAR, 0xFE, 1, SLA);//設定TWI編號 依據接線設定地址ADD
REGFPT(&TWAR, 0x01, 0, 0);//選擇擴播關閉
REGFPT(&DDRD, 0x03, 0, 3);//檢察並設定TWI通訊接腳為輸出
//---TWI串列通訊埠暫存器設定REGPUT---//
REGPUT(&TWBR, 1, 12);//設定TWI通訊工作時脈 TWBR預設值12
//---設定TMP175暫存器參數TWIM_trm---//
TWIM_trm(5, SLA, 0x02, 2, Ltemp, 10);//設定低溫門檻
TWIM_trm(5, SLA, 0x03, 2, Htemp, 10);//設定高溫門檻
//---TMP175暫存器旗標群參數設定TWIM_ftm---//
TWIM_ftm(5, SLA, 0x01, 0x01, 0, &SD, 10);//設定休眠模式
TWIM_ftm(5, SLA, 0x01, 0x02, 1, &TM, 10);//設定溫度比較模式TM=1
TWIM_ftm(5, SLA, 0x01, 0x04, 2, &POL, 10);//設定Alert極性 POL HI
TWIM_ftm(5, SLA, 0x01, 0x18, 3, &F1F0, 10);//設定延遲次數2
TWIM_ftm(5, SLA, 0x01, 0x60, 5, &R1R0, 10);//設定量測解析度0.5度C 9bits
//----計時中斷硬體設定----//
REGFPT(&TCCR2,0x48,3,1);//TIME2波形模式選擇方波
REGFPT(&TCCR2,0x07,0,5);//TIME2FreqDivide除頻值設定(除頻Clk/1024)
REGFPT(&TCCR2,0x30,4,1);//TIME2WareOut波形輸出致能
REGFPT(&TIMSK,0x80,7,1);//設定TIM2接腳輸出
uint16_t Data=215;//OCR2=215 Focn=25 Hz
REGPUT(&OCR2,1,Data);//set OCR2
sei();//致能中斷
while (1)
{
if (Interrupt==1)
{
if (temp[0]>=Htemp[0])
{
printf("High temperature alert\n");
}
else if (temp[0]<Ltemp[0])
{
printf("Low temperature alert\n");
}
Interrupt=0;
}
_delay_ms(500);
}
}
ISR(TIMER2_COMP_vect)//40ms
{
TWIM_rec(5, SLA, 0, 2, temp, 10);//讀取溫度
printf("Current temperature is %d.%d C\n", temp[0], temp[1]*10/256);
Interrupt=1;
}
```
## 流程圖
#### TCA9534A
### 1.TCA9534A輸出

### 2.TCA9534A輸入

#### TMP175
### 1. 休眠模式下單發量測溫度

### 2. 比較模式下過溫度中斷警告

### 3. 量測模式下固定週期量測並顯示

## 實驗數據
#### TCA9534A
### 1.TCA9534A輸出



### 2.TCA9534A輸入


#### TMP175
### 1. 休眠模式下單發量測溫度
#### 文字人機截圖
### 2. 比較模式下過溫度中斷警告
#### 文字人機截圖
### 3. 量測模式下固定週期量測並顯示
#### 文字人機截圖
#### 示波器量測ALERT波形
[請點我(觀看影片中3~4秒處)](https://ncu365-my.sharepoint.com/:v:/g/personal/oreo900930_office365_ncu_edu_tw/Ef7R6xVIIFBLunDGxIjY2W8BTAPnLte0QZTl6uJvfgkx-A?e=ZAfZp3)
## 驗收
### 驗收題目
* 將TMP175實時溫度顯示在七節管,到小數點第一位,並且可以單位F(華氏切換),C(攝氏),用一顆按鈕接TCA9534a。
* 並且量測模式超過設定值,然後傳到matlab劃出兩條單位溫度曲線,且可以用matlab傳OFF訊息回MCU將七段顯示器,歸為單位C顯示0度溫度。
* 除頻值設置16,最後須達到bit rate 約138K左右
* 
* 根據計算 TWPS設為2 TWBR設為2
* 且請用邏輯分析儀或示波器顯示結果
* 
### 驗收成果
### 遭遇問題&問題解決
1. TCA9534A輸出至七節管 P3 P4腳位無法拉到HIGH
* 測試從輸出0~9

```
SevenSegTable[]={0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111};
```
* 改輸出0b1111 1111

* TCA9534A輸出至七節管 P3 P4腳位還是無法拉到HIGH
* SDA/SCL通訊正常 是TCA9534A暫存器設定參數問題
2. 除頻值設置按照講義計算錯誤
* 參考原始datasheet重新計算
* 