# 介面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)