# 介面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輸出頻率及波寬實驗

### 2. 觀察單通道PWM波寬變化波形實驗

### 3. 觀察三通道PWM三相弦波輸出波形實驗

## 實驗數據
### 1. 觀察PWM輸出頻率及波寬實驗
* PWM1


* PWM2


### 2. 觀察單通道PWM波寬變化波形實驗
* sin


* sawtooth


### 3. 觀察三通道PWM三相弦波輸出波形實驗

* PWM1A, PWM1B
* PWM1B, PWM1C
* PWM1C, PWM1A
## 驗收
### 驗收題目
由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);
```

