dsPIC Tutorial 2-Các kỹ thuật cơ bản

Collapse
This is a sticky topic.
X
X
 
  • Giờ
  • Show
Clear All
new posts
  • namqn
    Trưởng lão PIC bang
    • Feb 2006
    • 3020

    #1

    dsPIC Tutorial 2-Các kỹ thuật cơ bản

    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,
    Attached Files
    Biển học mênh mông, sức người có hạn.

    Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
    http://www.picvietnam.com/forum/showthread.php?t=1263
  • namqn
    Trưởng lão PIC bang
    • Feb 2006
    • 3020

    #2
    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.


    Chúc thành công!

    Thân,
    Biển học mênh mông, sức người có hạn.

    Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
    http://www.picvietnam.com/forum/showthread.php?t=1263

    Comment

    • namqn
      Trưởng lão PIC bang
      • Feb 2006
      • 3020

      #3
      Của em đây!

      Thân,
      Attached Files
      Biển học mênh mông, sức người có hạn.

      Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
      http://www.picvietnam.com/forum/showthread.php?t=1263

      Comment

      • typhn
        Đệ tử 1 túi
        • Apr 2006
        • 19

        #4
        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

        Comment

        • namqn
          Trưởng lão PIC bang
          • Feb 2006
          • 3020

          #5
          Nguyên văn bởi typhn View Post
          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,
          Biển học mênh mông, sức người có hạn.

          Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
          http://www.picvietnam.com/forum/showthread.php?t=1263

          Comment

          • typhn
            Đệ tử 1 túi
            • Apr 2006
            • 19

            #6
            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).

            Comment

            • namqn
              Trưởng lão PIC bang
              • Feb 2006
              • 3020

              #7
              Nguyên văn bởi typhn View Post
              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,
              Biển học mênh mông, sức người có hạn.

              Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
              http://www.picvietnam.com/forum/showthread.php?t=1263

              Comment

              • longho559
                Nhập môn đệ tử
                • Jan 2007
                • 2

                #8
                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?
                Last edited by namqn; 26-02-2007, 05:47 PM.

                Comment

                • namqn
                  Trưởng lão PIC bang
                  • Feb 2006
                  • 3020

                  #9
                  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,
                  Biển học mênh mông, sức người có hạn.

                  Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
                  http://www.picvietnam.com/forum/showthread.php?t=1263

                  Comment

                  • hoanf
                    Đệ tử 3 túi
                    • Jun 2006
                    • 51

                    #10
                    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

                    Comment

                    • namqn
                      Trưởng lão PIC bang
                      • Feb 2006
                      • 3020

                      #11
                      Nguyên văn bởi hoanf View Post
                      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,
                      Biển học mênh mông, sức người có hạn.

                      Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
                      http://www.picvietnam.com/forum/showthread.php?t=1263

                      Comment

                      • ajack
                        Nhập môn đệ tử
                        • Jan 2008
                        • 6

                        #12
                        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

                        Comment

                        • namqn
                          Trưởng lão PIC bang
                          • Feb 2006
                          • 3020

                          #13
                          Nguyên văn bởi ajack View Post
                          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,
                          Biển học mênh mông, sức người có hạn.

                          Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
                          http://www.picvietnam.com/forum/showthread.php?t=1263

                          Comment

                          • ajack
                            Nhập môn đệ tử
                            • Jan 2008
                            • 6

                            #14
                            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...

                            Comment

                            • namqn
                              Trưởng lão PIC bang
                              • Feb 2006
                              • 3020

                              #15
                              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,
                              Biển học mênh mông, sức người có hạn.

                              Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
                              http://www.picvietnam.com/forum/showthread.php?t=1263

                              Comment

                              Working...