---
# System prepended metadata

title: 介面lab06

---

# 介面lab06
## 工作日誌
* 10/24 閱讀講義
## 程式碼
### 1. 觀察PWM輸出頻率及波寬實驗
```c
#include "c4mlib.h"
#define F_CPU 11059200UL

typedef struct {
	int p;
} FuncParaStr_t;

void PWM_OUTPUT(void *void_p);

int main(void)
{
	C4M_DEVICE_set();
	
	uint8_t PWMn;
	int freqDivi, Pulse;

	uint16_t ICR1value, OCRvalue;
	
	printf("Choose channel \nPWM1:1 \nPWM2:2 ");
	scanf("%d", &PWMn);
	
	if (PWMn==1)
	{
		printf("Choose FreqDivide:\n 1: clk/2\n 2: clk/8\n 3: clk/64\n 4: clk/256\n 5: clk/1024");
		scanf("%d", &freqDivi);
		printf("Choose WaveOut:\n P_PULSE:3 \n N_PULSE:2");
		scanf("%d", &Pulse);
		printf("Set output wave width < 2^16:\n");
		scanf("%d", &OCRvalue);
		
		REGFPT(&TCCR1A, 0X03, 0, 0);//波形模式選擇ICR3最高
		REGFPT(&TCCR1B, 0X18, 3, 2);//波形模式選擇中間對齊
		REGFPT(&TCCR1B, 0X07, 0, freqDivi);//除頻值N設定
		REGFPT(&TCCR1A, 0X0C, 2, Pulse);//C通道波形輸出正負脈波
		REGFPT(&DDRB, 0X80, 7, 1);//PB7輸出
		
		ICR1value = 2^16;
		REGPUT(&ICR1L, 2, &ICR1value);//設定最大波寬=2^16
		REGPUT(&OCR1CL, 2, &OCRvalue);//設定C通道輸出波寬
		REGFPT(&TIMSK, 0x04, 2, 1);//PWM1中斷致能
		float fpwm = 11059200/freqDivi/ICR1value/2;
		printf("fpwm = %f Hz\n", fpwm);
		
		PWMHWINT_LAY(PWM1Int_str, 1, 1);
		FuncParaStr_t PWMpara = {.p = 0 };
		uint8_t id = HWInt_reg(&PWM1Int_str, &PWM_OUTPUT, &PWMpara);
		HWInt_en(&PWM1Int_str, id, ENABLE);
		sei();
		
	}
	else if (PWMn==2)
	{
		printf("Choose FreqDivide:\n 1: clk/2\n 2: clk/8\n 3: clk/64\n 4: clk/256\n 5: clk/1024");
		scanf("%d", &freqDivi);
		printf("Choose WaveOut:\n P_PULSE:3 \n N_PULSE:2");
		scanf("%d", &Pulse);
		printf("Set output wave width < 2^8:\n");
		scanf("%d", &OCRvalue);
		
		REGFPT(&TCCR2, 0X48, 3, 8);//波形模式選擇中間對齊
		REGFPT(&TCCR2, 0X07, 0, freqDivi);//除頻值N設定
		REGFPT(&TCCR2, 0X30, 4, Pulse);//波形輸出正負脈波
		REGFPT(&DDRB, 0X80, 7, 1);//PB7輸出
		
		REGPUT(&OCR2, 1, &OCRvalue);//設定輸出波寬<2^8
		REGFPT(&TIMSK, 0x40, 6, 1);//PWM2中斷致能
		float fpwm = 11059200/freqDivi/510;
		printf("fpwm = %f Hz\n", fpwm);
		
		PWMHWINT_LAY(PWM2Int_str, 1, 1);
		FuncParaStr_t PWMpara = {.p = 0 };
		uint8_t id = HWInt_reg(&PWM2Int_str, &PWM_OUTPUT, &PWMpara);
		HWInt_en(&PWM2Int_str, id, ENABLE);
		sei();
	}
	
	while (1)
	{
		
	}
	
	return 0;
}

void PWM_OUTPUT(void *void_p)
{
	REGFPT(&PORTB, 0x80, 7, 1);
}
```
### 2. 觀察單通道PWM波寬變化波形實驗
```c
#include "c4mlib.h"
#define F_CPU 11059200UL

typedef struct {
	int p;
} FuncParaStr_t;

void PIPELINE_SET(void);
void PWM2_SET(void);
void ADC_SET(void);

void PwmPrePro_step(void* VoidStr_p);
void ADC_Single_end(void *void_p);
void ADCPostPro_step(void* VoidStr_p);

uint16_t singletrm=0;
float singleDigit[1][100] = {0};
uint8_t mat[1][100] = {0};
int flag=0;
int count=0;

int main(void)
{
	C4M_DEVICE_set();
	
	//----------FREQREDU_SET----------//
	TIM0_HW_LAY();
	hardware_set(&TIM0HWSet_str);
	TIMHWINT_LAY(timer0str, 0, 1);
	uint8_t period[20] = {251};
	FREQREDU_LAY(freqredustr, 3, 20, &OCR0, 1, period);
	
	uint8_t taskID = HWInt_reg(&timer0str, &FreqRedu_step, &freqredustr);
	HWInt_en(&timer0str, taskID, ENABLE);
	
	uint8_t Fid0, Fid1, Fid2;
	Fid0 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 0);
	Fid1 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 2);
	Fid2 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 3);
	FreqRedu_en(&freqredustr, Fid0, 1);
	FreqRedu_en(&freqredustr, Fid1, 1);
	FreqRedu_en(&freqredustr, Fid2, 1);
	//----------END----------//
	
	PIPELINE_SET();
	PWM2_SET();
	ADC_SET();
	HMI_snget_matrix( 4, 1, 100, &mat);
	
	sei();
	TRIG_NEXT_TASK(0);
	while (1);
}


void PIPELINE_SET(void)
{
	/*PIPELINE排程器工作方塊佈局及登錄*/
	FuncParaStr_t Task1_para = {.p = 0};
	FuncParaStr_t Task2_para = {.p = 0};
	FuncParaStr_t Task3_para = {.p = 0};

	uint8_t task1_name[] = "Task1\0";
	uint8_t task2_name[] = "Task2\0";
	uint8_t task3_name[] = "Task3\0";
	
	PIPELINE_LAY(3, 3, 20);
	uint8_t Pid1, Pid2, Pid3;
	
	Pid1 = Pipeline_reg(&SysPipeline_str, &PwmPrePro_step, &Task1_para, task1_name);
	Pid2 = Pipeline_reg(&SysPipeline_str, &ADC_Single_end, &Task2_para, task2_name);
	Pid3 = Pipeline_reg(&SysPipeline_str, &ADCPostPro_step, &Task3_para, task3_name);
}

void PWM2_SET(void)
{
	// 	PWM2_HW_LAY()
	// 	hardware_set(&PWM2HWSet_str);

	REGFPT(&TCCR2, 0X48, 3, 8);//波形模式選擇中間對齊
	REGFPT(&TCCR2, 0X07, 0, 4);//除頻值設定256
	REGFPT(&TCCR2, 0X30, 4, 3);//波形輸出正負脈波
	REGFPT(&DDRB, 0X80, 7, 1);//PB7輸出
	REGFPT(&TIMSK, 0x40, 6, ENABLE);//PWM2中斷致能
}

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,3);//設定工作時脈除頻8
	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 PwmPrePro_step(void *void_p)
{
	//printf("TASK1\n");
	uint8_t Data = mat[0][count];
	//printf("Data = %d\n",Data);
	REGPUT(&OCR2, 1, &Data);

	TRIG_NEXT_TASK(1);
}

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

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

```

### 3. 觀察三通道PWM三相弦波輸出波形實驗
```c
#include "c4mlib.h"
#define F_CPU 11059200UL

typedef struct {
	int p;
} FuncParaStr_t;

void FREQREDU_SET(void);
void PIPELINE_SET(void);
void PWM1_SET(void);
void ADC_SET(void);

void PwmPrePro_step(void* VoidStr_p);
void ADC_Single_end(void *void_p);
void ADCPostPro_step(void* VoidStr_p);

uint16_t singletrm0 = 0, singletrm1 = 0, singletrm2 = 0;
float singleDigit0[1][40] = {0};
float singleDigit1[1][40] = {0};
float singleDigit2[1][40] = {0};

uint16_t mat[1][120] = {0};
int flag=0;
int count=0;

int main(void)
{
	C4M_DEVICE_set();
	
	//----------FREQREDU_SET----------//
	TIM0_HW_LAY();
	hardware_set(&TIM0HWSet_str);
	TIMHWINT_LAY(timer0str, 0, 1);
	uint8_t period[20] = {251};
	FREQREDU_LAY(freqredustr, 3, 20, &OCR0, 1, period);
	
	uint8_t taskID = HWInt_reg(&timer0str, &FreqRedu_step, &freqredustr);
	HWInt_en(&timer0str, taskID, ENABLE);
	
	uint8_t Fid0, Fid1, Fid2;
	Fid0 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 0);
	Fid1 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 2);
	Fid2 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 3);
	FreqRedu_en(&freqredustr, Fid0, 1);
	FreqRedu_en(&freqredustr, Fid1, 1);
	FreqRedu_en(&freqredustr, Fid2, 1);
	//----------END----------//
	
	PIPELINE_SET();
	PWM1_SET();
	ADC_SET();
	HMI_snget_matrix( 5, 1, 120, &mat);
	
	sei();
	TRIG_NEXT_TASK(0);
	while (1);
}


void PIPELINE_SET(void)
{
	/*PIPELINE排程器工作方塊佈局及登錄*/
	FuncParaStr_t Task1_para = {.p = 0};
	FuncParaStr_t Task2_para = {.p = 0};
	FuncParaStr_t Task3_para = {.p = 0};

	uint8_t task1_name[] = "Task1\0";
	uint8_t task2_name[] = "Task2\0";
	uint8_t task3_name[] = "Task3\0";
	
	PIPELINE_LAY(3, 3, 20);
	uint8_t Pid1, Pid2, Pid3;
	
	Pid1 = Pipeline_reg(&SysPipeline_str, &PwmPrePro_step, &Task1_para, task1_name);
	Pid2 = Pipeline_reg(&SysPipeline_str, &ADC_Single_end, &Task2_para, task2_name);
	Pid3 = Pipeline_reg(&SysPipeline_str, &ADCPostPro_step, &Task3_para, task3_name);
}

void PWM1_SET(void)
{
// 	PWM1_HW_LAY()
// 	hardware_set(&PWM1HWSet_str);
	REGFPT(&TCCR1A, 0X03, 0, 0);//波形模式選擇ICR3最高
	REGFPT(&TCCR1B, 0X18, 3, 2);//波形模式選擇中間對齊
	REGFPT(&TCCR1B, 0X07, 0, 3);//除頻值N設定64
	REGFPT(&TCCR1A, 0XC0, 6, 3);//A通道波形輸出正負脈波
	REGFPT(&TCCR1A, 0X30, 4, 3);//B通道波形輸出正負脈波
	REGFPT(&TCCR1A, 0X0C, 2, 3);//C通道波形輸出正負脈波
	REGFPT(&DDRB, 0XE0, 5, 1);//PB5輸出
	REGFPT(&DDRB, 0X40, 6, 1);//PB6輸出
	REGFPT(&DDRB, 0X80, 7, 1);//PB7輸出
	
	uint16_t ICR1value = 1024;
	REGPUT(&ICR1L, 2, &ICR1value);//設定最大波寬=2^16
	REGFPT(&TIMSK, 0x04, 2, 1);//PWM1中斷致能
}

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,3);//設定工作時脈除頻8
	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 PwmPrePro_step(void *void_p)
{
	uint16_t Data=0;
	//printf("TASK1\n");
	Data = mat[0][count];
	//printf("OCR1AL = %d\n",Data);
	REGPUT(&OCR1AL, 2, &Data);
	Data = mat[0][count+40];
	//printf("OCR1BL = %d\n",Data);
	REGPUT(&OCR1BL, 2, &Data);
	Data = mat[0][count+80];
	//printf("OCR1CL = %d\n",Data);
	REGPUT(&OCR1CL, 2, &Data);

	Data = 0;
	TRIG_NEXT_TASK(1);
}

void ADC_Single_end(void *void_p)
{
	//printf("TASK2\n");
	
	REGFPT(&ADMUX,0x1F,0,0X00);//設定輸入通道PF0 ADC0-GND 5V
	REGFPT(&ADCSRA,0x40,6,1);//觸發 ADC 轉換
	while((ADCSRA & (1<<ADIF)) != (1<<ADIF));//轉換需時
	REGGET(&ADCL, 2, &singletrm0);//讀取 10 位元 uint16_t型態轉換結果
	
	REGFPT(&ADMUX,0x1F,0,0X01);//設定輸入通道PF1 ADC1-GND 5V
	REGFPT(&ADCSRA,0x40,6,1);//觸發 ADC 轉換
	while((ADCSRA & (1<<ADIF)) != (1<<ADIF));//轉換需時
	REGGET(&ADCL, 2, &singletrm1);//讀取 10 位元 uint16_t型態轉換結果
	
	REGFPT(&ADMUX,0x1F,0,0X02);//設定輸入通道PF2 ADC2-GND 5V
	REGFPT(&ADCSRA,0x40,6,1);//觸發 ADC 轉換
	while((ADCSRA & (1<<ADIF)) != (1<<ADIF));//轉換需時
	REGGET(&ADCL, 2, &singletrm2);//讀取 10 位元 uint16_t型態轉換結果
	
	TRIG_NEXT_TASK(2);
	//printf("single = %d\n", singletrm);
}

void ADCPostPro_step(void *void_p)
{
	//printf("TASK3\n");
	
	singleDigit0[0][count] = singletrm0*2.56/1024;
	singleDigit1[0][count] = singletrm1*2.56/1024;
	singleDigit2[0][count] = singletrm2*2.56/1024;
	
	if (count>=39)
	{
		if (!flag)
		{
			HMI_snput_matrix(8, 1, 40, &singleDigit0);
			HMI_snput_matrix(8, 1, 40, &singleDigit1);
			HMI_snput_matrix(8, 1, 40, &singleDigit2);
			flag = 1;
		}
		//cli();
		count = 0;
	}
	
	//printf("count = %d\n", count);
	count++;
	TRIG_NEXT_TASK(0);
}
```
## 流程圖
### 1. 觀察PWM輸出頻率及波寬實驗

![](https://i.imgur.com/JGKqQDI.png)


### 2. 觀察單通道PWM波寬變化波形實驗
![](https://i.imgur.com/Mquj7Dg.png)


### 3. 觀察三通道PWM三相弦波輸出波形實驗
![](https://i.imgur.com/P64wmNh.png)

## 實驗數據
### 1. 觀察PWM輸出頻率及波寬實驗
* PWM1
![](https://i.imgur.com/1lR5qTy.png)
![](https://i.imgur.com/YpQk0QY.jpg)

* PWM2
![](https://i.imgur.com/iPw1NPP.png)
![](https://i.imgur.com/zipSupQ.jpg)

### 2. 觀察單通道PWM波寬變化波形實驗
* sin
![](https://i.imgur.com/FIBOMhg.png)
![](https://i.imgur.com/5LGf6XG.jpg)

* sawtooth
![](https://i.imgur.com/4hz4FBl.png)
![](https://i.imgur.com/PEVUn7C.jpg)


### 3. 觀察三通道PWM三相弦波輸出波形實驗
![](https://i.imgur.com/TFp44Vv.png)
* PWM1A, PWM1B![](https://i.imgur.com/0HhlnDA.jpg)

* PWM1B, PWM1C![](https://i.imgur.com/ZYggmfD.jpg)

* PWM1C, PWM1A![](https://i.imgur.com/VLKIMTL.jpg)


## 驗收
### 驗收題目
由matlab產生三角波和正弦波資料給M128，
其中三角波的週期為正弦波的3/5，
請寫出程式碼並拍下PWM在示波器上的輸出波形結果。
### 驗收成果
```c
#include "c4mlib.h"
#define F_CPU 11059200UL

typedef struct {
	int p;
} FuncParaStr_t;

void FREQREDU_SET(void);
void PIPELINE_SET(void);
void PWM1_SET(void);
void ADC_SET(void);

void PwmPrePro_step(void* VoidStr_p);
void ADCPostPro_step(void* VoidStr_p);


uint16_t mat0[1][120] = {0};
uint16_t mat1[1][120] = {0};
int flag=0;
int count=0;

int main(void)
{
	C4M_DEVICE_set();
	
	//----------FREQREDU_SET----------//
	TIM0_HW_LAY();
	hardware_set(&TIM0HWSet_str);
	TIMHWINT_LAY(timer0str, 0, 1);
	uint8_t period[20] = {251};
	FREQREDU_LAY(freqredustr, 3, 20, &OCR0, 1, period);
	
	uint8_t taskID = HWInt_reg(&timer0str, &FreqRedu_step, &freqredustr);
	HWInt_en(&timer0str, taskID, ENABLE);
	
	uint8_t Fid0, Fid1;
	Fid0 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 0);
	Fid1 = FreqRedu_reg(&freqredustr, &Pipeline_step, &SysPipeline_str, 1, 2);
	FreqRedu_en(&freqredustr, Fid0, 1);
	FreqRedu_en(&freqredustr, Fid1, 1);
	//----------END----------//
	
	PIPELINE_SET();
	PWM1_SET();
	
	HMI_snget_matrix( 5, 1, 120, &mat0);
	HMI_snget_matrix( 5, 1, 120, &mat1);
	
	sei();
	TRIG_NEXT_TASK(0);
	while (1);
}


void PIPELINE_SET(void)
{
	/*PIPELINE排程器工作方塊佈局及登錄*/
	FuncParaStr_t Task1_para = {.p = 0};
	FuncParaStr_t Task2_para = {.p = 0};

	uint8_t task1_name[] = "Task1\0";
	uint8_t task2_name[] = "Task2\0";
	
	PIPELINE_LAY(3, 3, 20);
	uint8_t Pid1, Pid2;
	
	Pid1 = Pipeline_reg(&SysPipeline_str, &PwmPrePro_step, &Task1_para, task1_name);
	Pid2 = Pipeline_reg(&SysPipeline_str, &ADCPostPro_step, &Task2_para, task2_name);
}

void PWM1_SET(void)
{
// 	PWM1_HW_LAY()
// 	hardware_set(&PWM1HWSet_str);
	REGFPT(&TCCR1A, 0X03, 0, 0);//波形模式選擇ICR3最高
	REGFPT(&TCCR1B, 0X18, 3, 2);//波形模式選擇中間對齊
	REGFPT(&TCCR1B, 0X07, 0, 3);//除頻值N設定64
	REGFPT(&TCCR1A, 0XC0, 6, 3);//A通道波形輸出正負脈波
	REGFPT(&TCCR1A, 0X30, 4, 3);//B通道波形輸出正負脈波
	REGFPT(&TCCR1A, 0X0C, 2, 3);//C通道波形輸出正負脈波
	REGFPT(&DDRB, 0XE0, 5, 1);//PB5輸出
	REGFPT(&DDRB, 0X40, 6, 1);//PB6輸出
	REGFPT(&DDRB, 0X80, 7, 1);//PB7輸出
	
	uint16_t ICR1value = 1024;
	REGPUT(&ICR1L, 2, &ICR1value);//設定最大波寬
	REGFPT(&TIMSK, 0x04, 2, 1);//PWM1中斷致能
}


void PwmPrePro_step(void *void_p)
{
	uint16_t Data=0;
	//printf("TASK1\n");
	Data = mat0[0][count];
	//printf("OCR1AL = %d\n",Data);
	REGPUT(&OCR1AL, 2, &Data);
	Data = mat1[0][count];
	//printf("OCR1BL = %d\n",Data);
	REGPUT(&OCR1BL, 2, &Data);

	Data = 0;
	TRIG_NEXT_TASK(1);
}


void ADCPostPro_step(void *void_p)
{
	//printf("TASK2\n");
	
	if (count>=120)
	{
		//cli();
		count = 0;
	}
	
	//printf("count = %d\n", count);
	count++;
	TRIG_NEXT_TASK(0);
}
```
* matlab
```
clc
clear
close all

port = remo_open(6);

u = zeros(1,120);
w=1;
t=0.01;
x = 1:120;
for i = 1:120
	u0(i) = 512*(sin(2*pi*w*i*t)+1);
end
u0 = cast(u0,'uint16');

subplot(2,1,1);
plot(x, u0, 'B-');

u1= 512*(sawtooth(0.02*2/1.2*pi*x,0.5)+1);
u1 = cast(u1,'uint16');

subplot(2,1,2);
plot(x, u1, 'B-');

erru0 = remo_snput_matrix(port,u0);
erru1 = remo_snput_matrix(port,u1);

remo_close(port);

```
![](https://i.imgur.com/toAZwIs.png)
![](https://i.imgur.com/YO6WyQW.jpg)


