Cám ơn anh Nam nhé, em đã làm đúng như anh bảo nhưng LCD vẫn không chịu hiển thị, em kiểm tra phần cứng không có vấn đề gì, em thử test chương trình cũ của một anh ( tên là H ) ra đi không một lời chăn chối thì LCD vẫn chạy. Thôi em đành bỏ cái mạch đó đi làm lại mạch mới, nhưng em vẫn ấm ức lắm, rồi có ngày em sẽ tìm được nguyên nhân.
Thưa anh em nhận được nhiệm vụ mới đó là thực hiện điều khiển số PFC để ổn định áp ra......
Em đã viết code mong em xem giúp em :
Code:
////////////////////////// tham khao tutorial 06.01 cua anh Nguyen Quang Nam //////////////////
#include <p30f4011.h>
#include <dsp.h>
_FOSC(CSW_FSCM_OFF & FRC_PLL4);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);
//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define PWM_PORT PORTE //Cac tin hieu PWM nam o cong E
#define PWM_TRIS TRISE //Thanh ghi 3 trang thai cho cac tin hieu PWM
#define PWM_LAT LATE //Thanh ghi chot cac tin hieu PWM
#define Fcy 8000000 //Tan so thuc thi lenh
#define Fpwm 40000 //Tan so PWM = 40 kHz
//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_MCPWM(void);
void Init_ADC10(void);
void PID_Cal(float kp,float ki,float kd,fractional refer,fractional measu);
fractional ADC_Vo,ADC_Vi,ADC_I,Vc,Vx;
tPID fooPID;
fractional abcCoefficient[3] __attribute__ ((section (".xbss, bss, xmemory")));
fractional controlHistory[3] __attribute__ ((section (".ybss, bss, ymemory")));
fractional kCoeffs[] = {0,0,0};
int main (void)
{
Init_PORTS(); //Khoi tao cac cong I/O
Init_MCPWM(); //Khoi tao module PWM
Init_ADC10(); //Khoi tao module ADC
while (1) Nop();
}
//Chuong trinh con khoi tao cac cong I/O, de xuat cac tin hieu PWM, va doc tin
//hieu dieu chinh cua bien tro tai AN0
void Init_PORTS(void) {
PWM_LAT = 0; //Xoa thanh ghi chot cac tin hieu PWM
PWM_TRIS = 0xFFC0; //Cac tin hieu PWM nam tai RE0..RE5
TRISB = 0x000B; //Chan RB0,1,3 la ngo vao , cac chan khac
//la ngo ra
}
//Chuong trinh con khoi tao module chuyen doi A/D, doc ngo vao AN0
void Init_ADC10(void) {
// ADCON2bits.CHPS = 3; // Convert CH0, CH1, CH2 and CH3
ADCON1bits.FORM = 3; //Dinh dang du lieu ra Q15
ADPCFG = 0xFFF8; //Cac chan khac la digital, chan RB0,1,2 la analog
ADCON1 = 0x0060; //Module PWM cham dut lay mau va kich hoat
//viec chuyen doi A/D
// ADCON1 = 0x0040; //Timer 3 cham dut lay mau va kich hoat
//viec chuyen doi A/D
ADCON2 = 0;
ADCHS = 0x0008; //Kenh 0 doc tin hieu giua AN0,AN1,AN2 va AVss
ADCSSL = 0; //Khong quet cac ngo vao
ADCON3 = 0x0103; //Dung 1 TAD cho lay mau, dung clock he thong,
//TAD = 2xTcy = 250 ns
/* TMR3 = 0; //Xoa thanh ghi dem cua Timer 3
PR3 = 0x03E8; //Nguong delay cho TMR3 la khoang 1 ms
T2CON = 0x8010; //Prescale = 1:8, bat cho TMR3 chay
*/
_ADIF = 0; //Xoa co ngat ADC
_ADIE = 1; //Cho phep ngat ADC
_ADON = 1; //Bat module ADC
_ASAM = 1; //Khoi dong che do tu dong lay mau
}
//Chuong trinh con khoi tao module PWM
void Init_MCPWM(void) {
PTPER = Fcy/Fpwm - 1; //Dat thanh ghi chu ky voi tan so PWM = 40 kHz
SEVTCMP = PTPER;
PWMCON1 = 0x070F; //Chi dung cac chan PxL, mot cach doc lap
OVDCON = 0xFF00; //Khong dung overdrive
PDC1 = 0x0100;
PWMCON2 = 0x0F00; //Postscale = 1:16
PTCON = 0x8000; //Kich hoat module PWM
}
void PID_Cal(float kp,float ki,float kd,fractional refer,fractional measu)
{
fooPID.abcCoefficients = &abcCoefficient[0]; /*Set up pointer to derived coefficients */
fooPID.controlHistory = &controlHistory[0]; /*Set up pointer to controller history samples */
PIDInit(&fooPID); /*Clear the controler history and the controller output */
kCoeffs[0] = Q15(kp);
kCoeffs[1] = Q15(ki);
kCoeffs[2] = Q15(kd);
// kCoeffs[0] = Q15(0.7);
// kCoeffs[1] = Q15(0.2);
// kCoeffs[2] = Q15(0.07);
PIDCoeffCalc(&kCoeffs[0], &fooPID); /*Derive the a,b, & c coefficients from the Kp, Ki & Kd */
//fooPID.controlReference = Q15(0.74) ;
fooPID.controlReference = refer;
fooPID.measuredOutput = measu ;
PID(&fooPID);
}
//Trinh phuc vu ngat cho ADC
void _ISR _ADCInterrupt(void)
{
ADC_Vo = ADCBUF0 >> 1 ;
PID_Cal(27,0.04211,0,0x1999,ADC_Vo); // V_refer = 1V
Vc = fooPID.controlOutput;
ADC_Vi = ADCBUF1 >> 1;
Vx = Vc*ADC_Vi; // tran !!!!!...........
ADC_I = ADCBUF2 >> 1;
PID_Cal(1.777,0.1479,0,Vx,ADC_I);
PDC1 = fooPID.controlOutput;
_ADIF = 0;
}
Nguyên lý như trong hình anh ạ. Và thuật toán của em như sau:
3 Biến đổi AD đưa vào 3 chân AN0,1,2. ( ở phần khai báo không biết có đúng không )
Phần tính toán PI của áp và dòng em thực hiện trong vong ngắt của ADC:
Bằng suy nghĩ của một nông dân, em cứ thực hiện từng bước tính toán như sơ đồ của nó.
Em đình dạng dữ liều ra kiểu fractional (Q15) cho ADC, thưa anh có phải khi biến đổi ADC ở 3 đầu vào thì kết quả của từng việc biến đổi sẽ lưu lần lượt ở ADCBUF0,1,2 không hả anh ?
và khi em thực hiện phép nhân Vx = Vc*ADC_Vi; liệu rằng nhân 2 số kiểu fractional nó có tràn không anh và cách xử lý ra sao ?
Liệu răng chương trình này có điều khiển được không anh nhỉ, Em tham khảo nhiều tài liệu , thấy họ viết code rất phức tạp, dùng ngắt timer, ngắt PWM, ADC, .....