---
# System prepended metadata

title: 介面lab05

---

# 介面lab05
## 工作日誌
* 10/4 閱讀講義
## 程式碼
### 1. DAC介面卡原型試作


```c
#include "c4mlib.h"
#define F_CPU 11059200UL

void SPI_SET(void);

int main(void)
{
	C4M_DEVICE_set();
	
	uint16_t data=2560;// 3 = 2*2.4*2560/4096
	SPI_SET();
	
	while (1)
	{
		REGFPT(&PORTF,1,0,0);
		_delay_ms(10);
		ASA_SPIM_trm(2,9,0x50,2,&data,10);//對A通達雙倍參考電壓輸出
		REGFPT(&PORTF,1,0,1);
	}
}

void SPI_SET(void)
{
	/*SPI串列通訊埠設定旗標群*/
	REGFPT(&SPSR,0x01,0,1);//選擇雙倍工作時脈
	REGFPT(&SPCR,0x03,0,0);//設定工作時脈除頻值4
	REGFPT(&SPCR,0x04,2,0);//同步時脈讀寫 前收後送
	REGFPT(&SPCR,0x08,3,0);//同步時脈前緣 前緣為上
	REGFPT(&SPCR,0x10,4,1);//主僕選擇 主
	REGFPT(&SPCR,0x20,5,0);//SPI資料傳輸順序 高位元先送
	REGFPT(&DDRB,0x0F,0,7);//設定 MOSI、SCK、SS 輸出，MISO 接腳為輸入
	REGFPT(&DDRF,0xE0,5,7);//設定 ASAID 接腳為輸出
	REGFPT(&DDRF,0x0F,0,1);//設定SPI SS8 PF0接腳為CS
	
	/*SPI串列通訊埠控制旗標群*/
	REGFPT(&SPCR,0x80,7,0);//SPI中斷禁能
	REGFPT(&SPCR,0x40,6,1);//SPI致能
	REGFPT(&PORTF,1,0,1);//CS初始值1
}

```

### 2. 使用SPI DAC卡完成ADC DAC完成控制迴路
```c
#include "c4mlib.h"
#define F_CPU 11059200UL

//----------降頻結構設定----------//
#define Taskblock_INI {.state=0,.FBFunc_p=NULL,.FBPara_p=NULL}
TaskBlock_t c[6]={Taskblock_INI,Taskblock_INI,Taskblock_INI,Taskblock_INI,Taskblock_INI,Taskblock_INI};

#define PhaseDivi_INI {.Divi=1,.DiviCount=0,.phase=0}
PhaseDivi_t b=PhaseDivi_INI;

uint16_t period=1;//改位移
#define FreqReduStr_INI {.Cycle=4,.Counter=0,.TaskId=0,.MaxTask=6,.Total=0,.Divi_p=&b,.Task_p=c,.Period_p=&period}
FreqReduStr_t a=FreqReduStr_INI;
//----------end----------//


uint8_t Pid0, Pid1, Pid2;
uint8_t Fid0, Fid1, Fid2;
uint8_t task0[]="Task0";
uint8_t task1[]="Task1";
uint8_t task2[]="Task2";

void SPI_SET(void);
void TIMER2_SET(void);
void ADC_SET(void);
void FREQREDU_SET(void);
void PIPELINE_SET(void);

void DAC_output(void);
void ADC_Single_end(void);
void record(void);

uint16_t singletrm=0, difftrm=0;
float singleDigit[1][100] = {0};
uint16_t mat[1][100] = {0};
int flag=0;
int count=0;
uint16_t Dn=2560;

int main(void)
{
	C4M_DEVICE_set();
	
	SPI_SET();
	TIMER2_SET();
	ADC_SET();
	FREQREDU_SET();
	PIPELINE_SET();
	
	HMI_snget_matrix( 5, 1, 100, &mat);
	
	sei();
	TRIG_NEXT_TASK(0);
	while (!flag)
	{
		
	}
}

void SPI_SET(void)
{
	/*SPI串列通訊埠設定旗標群*/
	REGFPT(&SPSR,0x01,0,1);//選擇雙倍工作時脈
	REGFPT(&SPCR,0x03,0,0);//設定工作時脈除頻值4
	REGFPT(&SPCR,0x04,2,0);//同步時脈讀寫 前收後送
	REGFPT(&SPCR,0x08,3,0);//同步時脈前緣 前緣為上
	REGFPT(&SPCR,0x10,4,1);//主僕選擇 主
	REGFPT(&SPCR,0x20,5,0);//SPI資料傳輸順序 高位元先送
	REGFPT(&DDRB,0x0F,0,7);//設定 MOSI、SCK、SS 輸出，MISO 接腳為輸入
	REGFPT(&DDRF,0xE0,5,7);//設定 ASAID 接腳為輸出
	REGFPT(&DDRF,0x0F,0,1);//設定SPI SS8 PF0接腳為CS
	
	/*SPI串列通訊埠控制旗標群*/
	REGFPT(&SPCR,0x80,7,0);//SPI中斷禁能
	REGFPT(&SPCR,0x40,6,1);//SPI致能
	REGFPT(&PORTF,1,0,1);//CS初始值1
}

void TIMER2_SET(void)
{
	//----計時中斷硬體設定----//
	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
}

void ADC_SET(void)
{
	/*ADC設定旗標群*/
	REGFPT(&ADMUX,0x1F,0,0x1F);//設定輸入通道Calibrate
	REGFPT(&ADMUX,0xC0,6,3);//設定參考電壓2.56
	REGFPT(&ADMUX,0x20,5,0);//設定10位元轉換
	REGFPT(&ADCSRA,0x07,0,2);//設定工作時脈除頻4
	REGFPT(&ADCSRA,0x20,5,0);//禁能觸發轉換
	REGFPT(&ADCSRA,0x08,3,0);//禁能ADC中斷
	REGFPT(&DDRF,0x0F,0,0);//設定ADC接腳為輸入
	REGFPT(&ADCSRA,0x80,7,1);//致能ADC
	REGFPT(&ADCSRA,0x40,6,1);//觸發 ADC 轉換
}

void FREQREDU_SET(void)
{
	/*降頻執行器*/
	Fid0 = FreqRedu_reg(&a, &Pipeline_step, &SysPipeline_str, 1, 0);
	Fid1 = FreqRedu_reg(&a, &Pipeline_step, &SysPipeline_str, 1, 2);
	Fid2 = FreqRedu_reg(&a, &Pipeline_step, &SysPipeline_str, 1, 3);
	FreqRedu_en(&a, Fid0, 1);
	FreqRedu_en(&a, Fid1, 1);
	FreqRedu_en(&a, Fid2, 1);
}

void PIPELINE_SET(void)
{
	/*PIPELINE排程器工作方塊佈局及登錄*/
	PIPELINE_LAY(3, 3, 10);
	Pid0 = Pipeline_reg(&SysPipeline_str, DAC_output, NULL, task0);
	Pid1 = Pipeline_reg(&SysPipeline_str, ADC_Single_end, NULL, task1);
	Pid2 = Pipeline_reg(&SysPipeline_str, record, NULL, task2);
	//printf("%d %d %d\n", aa, bb, cc);
}

void DAC_output(void)
{
	if (!flag)
	{
		Dn = mat[0][count];
		//printf("Dn: %d = mat[0][%d]\n", Dn, count);
		
		REGFPT(&PORTF,1,0,0);
		_delay_ms(1);
		ASA_SPIM_trm(2,9,0x50,2,&Dn,10);//對A通達雙倍參考電壓輸出
		REGFPT(&PORTF,1,0,1);

		TRIG_NEXT_TASK(1);
	}
}

void ADC_Single_end(void)
{
	REGFPT(&ADMUX,0x1F,0,0X01);//設定輸入通道PF1 ADC1-GND 5V
	_delay_ms(10);
	REGFPT(&ADCSRA,0x40,6,1);//觸發 ADC 轉換
	_delay_ms(10);
	REGGET(&ADCL, 2, &singletrm);//讀取 10 位元 uint16_t型態轉換結果
	TRIG_NEXT_TASK(2);
	//printf("single = %d\n", singletrm);
}

void record(void)
{
	
	singleDigit[0][count] = singletrm*5/1024;
	
	if (count>=99)
	{
		//cli();
		HMI_snput_matrix(8, 1, 100, &singleDigit);
		flag = 1;
		count = 0;
	}
	
	//printf("count = %d\n", count);
	count++;
	TRIG_NEXT_TASK(3);
}



ISR(TIMER2_COMP_vect)
{
	FreqRedu_step(&a);
}
```
## 流程圖
### 1. DAC介面卡原型試作
![](https://i.imgur.com/rXLX77N.png)

### 2. 使用SPI DAC卡完成ADC DAC完成控制迴路
![](https://i.imgur.com/RsuYyI1.png)


## 實驗數據
### 1. DAC介面卡原型試作
![](https://i.imgur.com/9j3ecO9.jpg)


### 2. 使用SPI DAC卡完成ADC DAC完成控制迴路
![](https://i.imgur.com/egyyX5i.jpg)
![](https://i.imgur.com/zvbqhAa.png)


## 驗收

### 驗收題目
(D)DAC原理是?A 積分器 B 微分器 C 乘法器 D 加法器 E 減法器

vin接可變電阻，用DAC來做ADC，輸出結果print出來
![](https://i.imgur.com/mZEXaCy.jpg)
### 驗收成果
* Vin=4.05 V
![](https://i.imgur.com/LeLBG2o.png)
![](https://i.imgur.com/4K9Qk3V.jpg)

* Vin=4.40 V
![](https://i.imgur.com/fRlzCuf.png)
![](https://i.imgur.com/E9sW5Ql.jpg)

* Vin=4.23 V
![](https://i.imgur.com/hz9g153.png)
![](https://i.imgur.com/hBEnFBm.jpg)



