PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   dsPIC - Bộ điều khiển tín hiệu số 16-bit (http://www.picvietnam.com/forum/forumdisplay.php?f=29)
-   -   dsPIC Tutorial 2-Các kỹ thuật cơ bản (http://www.picvietnam.com/forum/showthread.php?t=410)

namqn 03-05-2006 11:39 PM

dsPIC Tutorial 2-Các kỹ thuật cơ bản
 
2 Attachment(s)
Tutorial 2 cho dsPIC, viết trong ASM30. Bà con đừng nôn nóng nhé, sẽ có các tutorial viết bằng C30. Những vấn đề cơ bản về dsPIC nên được viết bằng ASM30, để hiểu rõ hơn cấu trúc của chip.

Tutorial này chỉ có các ví dụ về LED, nhưng có nhiều kỹ thuật cơ bản và khá nhiều lệnh cơ bản được đề cập, do đó các bạn đừng bỏ qua nó. Tôi sẽ dựa vào những kỹ thuật và lệnh cơ bản này để viết tiếp các tutorial khác.

Các tập tin nguồn và .hex nằm trong tập tin .zip nhé.

Chúc thành công nhé!

Thân,

namqn 08-08-2006 07:58 PM

Như đã thông báo, dưới đây là link để download các mã nguồn viết trong C30 (và các tập tin .hex đã được dịch ra) cho các ví dụ của tutorial này. Các mã nguồn C30 được chuyển đổi từ các mã nguồn ASM30, với chú thích khá chi tiết, do đó tôi sẽ không viết tutorial cho phiên bản C30.
http://picvietnam.com/download/uploa...n/Vidu2C30.zip

Chúc thành công!

Thân,

namqn 23-11-2006 06:49 PM

1 Attachment(s)
Của em đây!

Thân,

typhn 26-11-2006 10:01 PM

Chào bác nam.trước em có làm với pic6F877A,bây giờ em chuyển sang học về DSPIC.
Bác có thể nói rõ hơn về thanh ghi LATX được ko bác.
Con 877A ko có thanh ghi này và em đọc trong datasheet thì ko hiểu lắm.
Thanh ghi TrisX thì vẫn giống 877A,để định ngiã cổng vào/ra
Còn thanh ghi PortX trong 877A để xuất dữ liệu ra là mức cao hay thấp.
Còn trong các ví dụ của bác,em chưa thấy được vai trò của PortX
Và dường như bác toàn sử dụng LatX.
Bác nói rõ hơn cho em được ko
Thanks bác

namqn 27-11-2006 02:25 AM

Trích:

Nguyên văn bởi typhn (Post 6146)
Chào bác nam.trước em có làm với pic6F877A,bây giờ em chuyển sang học về DSPIC.
Bác có thể nói rõ hơn về thanh ghi LATX được ko bác.
Con 877A ko có thanh ghi này và em đọc trong datasheet thì ko hiểu lắm.
Thanh ghi TrisX thì vẫn giống 877A,để định ngiã cổng vào/ra
Còn thanh ghi PortX trong 877A để xuất dữ liệu ra là mức cao hay thấp.
Còn trong các ví dụ của bác,em chưa thấy được vai trò của PortX
Và dường như bác toàn sử dụng LatX.
Bác nói rõ hơn cho em được ko
Thanks bác

Trong các PIC cấp thấp (chẳng hạn như PIC16F877A), chỉ có một thanh ghi xuất nhập, và do hiệu ứng read-modify-write, các thao tác đối với các thanh ghi ngõ vào/ngõ ra có thể gây ra những khó khăn, buộc người dùng phải thực hiện các chuỗi thao tác nhất định để tránh những rắc rối có thể có. Tôi đã nói về read-modify-write ở một luồng khác, bạn hãy dùng chức năng Search của diễn đàn để tìm.

Kể từ dòng PIC cấp cao (PIC18), Microchip đã sử dụng hai thanh ghi đệm cho các thao tác xuất nhập, là LATx và PORTx. Như vậy, khi ghi ra các ngõ ra, chúng ta sẽ thao tác thanh ghi LATx, còn khi đọc vào từ các ngõ vào, chúng ta sẽ thao tác thanh ghi PORTx, và sẽ tránh được các rắc rối liên quan đến hiệu ứng read-modify-write.

Bạn có thể thấy tôi sử dụng các thanh ghi PORTx ở tutorial 3, khi đọc trạng thái của các switch.

Thân,

typhn 27-11-2006 08:46 PM

ah,thì ra là vậy,cảm ơn bác.
Bác cho em hỏi câu nữa,nếu bác có thời gian.
Nếu 1 cổng định nghĩa là lối vào(như RE0) chẳng hạn thì nó ở trạng thái
trở kháng cao phải ko bác( tức là ko phải mức 0 mà cũng chả phải mức 1).

namqn 28-11-2006 01:25 AM

Trích:

Nguyên văn bởi typhn (Post 6152)
ah,thì ra là vậy,cảm ơn bác.
Bác cho em hỏi câu nữa,nếu bác có thời gian.
Nếu 1 cổng định nghĩa là lối vào(như RE0) chẳng hạn thì nó ở trạng thái
trở kháng cao phải ko bác( tức là ko phải mức 0 mà cũng chả phải mức 1).

Một chân được định nghĩa là ngõ vào sẽ có bộ đệm ngõ ra bị disable. Chân đó sẽ được dùng như một ngõ vào dạng CMOS, với đặc tính Schmitt Trigger cho đa số chân.

Thân,

longho559 26-02-2007 12:06 PM

Code:

//Chuong trinh con khoi tao Timer 1, tran sau moi 1 giay o muc xung 8 Mips
void Init_TMR1(void) {
        TMR1 = 0;                //Xoa so dem trong TMR1
        PR1 = 0x7A12;                //Nguong tran la 1 giay tuong ung voi clock = 32 MHz
        _T1IF = 0;                //Xoa co ngat cua Timer 1
        T1CON = 0x8030;                //Dung fcy lam clock, prescale = 1:256, bat Timer 1
        _T1IE = 1;                //Cho phep ngat Timer 1
}

Trong đoạn chương trình trên em ko hiểu phần nhập giá trị PR1 = 0x7A12; sao lại ra 1 giây và phần T1CON = 0x8030; anh Nam có thể giải thích rõ hơn được ko?

namqn 26-02-2007 05:55 PM

T1CON<5:4> = '11' sẽ cho prescale là 1:256 (nghĩa là 256 chu kỳ máy thì timer 1 mới đếm thêm 1 đơn vị), và T1CON<15> = '1' để bật timer. Vậy T1CON = 1000 0000 0011 0000 = 0x8030.

PR1 = 0x7A12 = 31250.

Với tần số thực thi lệnh (Fosc/4) = 8 MIPS = 8000000, thời gian để timer 1 tràn là 8000000/(256*31250) = 1 (giây).

Thân,

hoanf 10-08-2007 11:17 AM

Chào anh namqn!

Trong tài liệu của anh đưa, em có thấy sử dụng chương trình mô phỏng dsPIC30F4012. Anh có thể cho biết đó là chương trình mô phỏng gì và share chương trình đó được kô.

Thanks
hoanf

namqn 10-08-2007 06:06 PM

Trích:

Nguyên văn bởi hoanf (Post 10641)
Chào anh namqn!

Trong tài liệu của anh đưa, em có thấy sử dụng chương trình mô phỏng dsPIC30F4012. Anh có thể cho biết đó là chương trình mô phỏng gì và share chương trình đó được kô.

Thanks
hoanf

Có lẽ bạn nhìn vào sơ đồ nguyên lý của mạch nên nhận xét như vậy. Tôi chỉ tạo ra ký hiệu cho dsPIC4012 trong Proteus thôi, chứ ngoài MPLAB SIM ra thì tôi chưa biết có phần mềm nào có thể mô phỏng dsPIC.

Thân,

ajack 03-03-2008 05:51 PM

Code:

// Timer 1 initialize: Internal Cycle Clock, với period_value = 16000, internal cycle là 16MIPs
void init_Timer1 (unsigned int Period_Value)
{
        T1CONbits.TON = 0;                // Disable Timer
        T1CONbits.TCS = 0;                // Select internal instruction cycle clock
        T1CONbits.TGATE = 0;        // Disable Gated Timer mode
        T1CONbits.TCKPS = 0b00;        // Select 1:1 Prescaler
        TMR1 = 0x00;                        // Clear timer register
        PR1 = Period_Value;        // Load the period value,
        IPC0bits.T1IP = 0x01;        // Set Timer 1 Interrupt Priority Level
        IFS0bits.T1IF = 0;                // Clear Timer 1 Interrupt Flag
        IEC0bits.T1IE = 1;                // Enable Timer1 interrupt
        T1CONbits.TON = 1;                // Start Timer
}

Không hiểu tại sao mà mình không tạo được interrupt 1ms, mà lâu hơn 1ms

namqn 03-03-2008 06:41 PM

Trích:

Nguyên văn bởi ajack (Post 14619)
Code:

// Timer 1 initialize: Internal Cycle Clock, với period_value = 16000, internal cycle là 16MIPs
void init_Timer1 (unsigned int Period_Value)
{
        T1CONbits.TON = 0;                // Disable Timer
        T1CONbits.TCS = 0;                // Select internal instruction cycle clock
        T1CONbits.TGATE = 0;        // Disable Gated Timer mode
        T1CONbits.TCKPS = 0b00;        // Select 1:1 Prescaler
        TMR1 = 0x00;                        // Clear timer register
        PR1 = Period_Value;        // Load the period value,
        IPC0bits.T1IP = 0x01;        // Set Timer 1 Interrupt Priority Level
        IFS0bits.T1IF = 0;                // Clear Timer 1 Interrupt Flag
        IEC0bits.T1IE = 1;                // Enable Timer1 interrupt
        T1CONbits.TON = 1;                // Start Timer
}

Không hiểu tại sao mà mình không tạo được interrupt 1ms, mà lâu hơn 1ms

Mức độ lâu hơn ra sao: lâu hơn một chút, hay gấp đôi, gấp ba, hay nhiều hơn nữa? Bạn dựa vào đâu để cho rằng dsPIC chạy ở 16 MIPS?

Thân,

ajack 03-03-2008 07:11 PM

mình đã config cho dsPIC chạy ở chế độ 16 MPIs như sau:
Code:

_FOSCSEL(FNOSC_FRC);  // Select Internal FRC at POR
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);  // Enable Clock Switching and Configure POSC in XT mode
_FWDT(FWDTEN_OFF);  // Disable Watchdog Timer

int main (void)
{
            // Configure PLL prescaler, PLL postscaler, PLL divisor
        PLLFBD = 62;                        // M = 64
        CLKDIVbits.PLLPOST = 1;        // N2 = 4        N2 = 2 x (PLLPOST+1)
        CLKDIVbits.PLLPRE = 2;        // N1 = 4        N1 = PLLPRE + 2

        // Fosc calculation equation:
        // Fosc = Fin x M/(N1+N2) = 8x64/(4x4) = 32MHz
        // Fcy = 0.5Fosc = 16MIPs

/******* Clock Switching *******/
        // Set New Oscillator Selection
        __builtin_write_OSCCONH(3);

        // Request Clock Switching by Setting OSWEN bit
        __builtin_write_OSCCONL(1);

        // Wait for Clock switch to occur
        while(OSCCONbits.LOCK != 1);
...
}

tại vì trong datasheet của dsPIC33F, mình thấy nó ghi là không nên thay đổi những thông số của PLL, nên để lúc đầu là internal FRC rồi chỉnh thông số, rồi sau đó hãy chuyển sang PriO w/ PLL
Nhưng bạn thấy trên phần init_Timer1 của mình intialize như vậy thì đúng là nếu như dsPIC chạy ở 16 MIPs thì timer sẽ interrupt ở 1ms chứ?
Hơn nữa, đây là intterupt trong timer1 để mình kiểm tra:
Code:

// Timer 1 Interrupt Routine
void __attribute__((__interrupt__)) _T1Interrupt( void )
{
        _count++;
        home_it();
        line_2();
        LATAbits.LATA4 = ~LATAbits.LATA4;
        if ( _count==1000 )
        {
                _count = 0;
                LATAbits.LATA5 = ~LATAbits.LATA5;  // PORTA.5 nối với đèn LED
        }

        IFS0bits.T1IF = 0;                        // Clear Timer 1 flag
}

đáng lý ra thì cứ phải 1s là đèn LED sẽ nhấp nháy, vậy mà chắc cũng 10s...

namqn 03-03-2008 08:25 PM

Bạn thử comment các hàm home_it() và line2() xem. Ngắt của bạn xảy ra mỗi ms, không nên để các hàm xuất tín hiệu ra LCD (tôi đoán vậy) vào trình xử lý ngắt.

Thân,


Múi giờ GMT. Hiện tại là 12:12 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam