PIC Vietnam

Go Back   PIC Vietnam > Truyền thông > Giao tiếp USB, CAN, I2C, SPI, USART...

Tài trợ cho PIC Vietnam
Trang chủ Đăng Kí Hỏi/Ðáp Thành Viên Lịch Bài Trong Ngày Vi điều khiển

Giao tiếp USB, CAN, I2C, SPI, USART... Những giao tiếp được tích hợp trên PIC

Trả lời
 
Ðiều Chỉnh Xếp Bài
Old 11-02-2009, 05:25 PM   #1
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Smile Từng bước tiếp cận và chinh phục giao thức CAN của dsPIC (30F4012)

Thời gian vừa qua tôi tìm cách làm giao thức CAN nhưng tìm trên PICVN thấy cũng không nhiều lắm và có vẻ như cũng chưa có tiền bối nào dạy cụ thể việc này, sau một thời gian mò mẫm tôi đã làm được cho 2 em dsPIC30f4012 nói chuyện được với nhau (tất nhiên là có sự trợ giúp của 2 em MCP2551) nên tôi mở ra mục này để nếu ai quan tâm có thể cùng tham gia và tiếp cận nhanh hơn với CAN trên dsPIC mà ở đây tôi chọn ví dụ là con 30F4012
Đầu tiên nếu bạn quan tâm, xin hãy đọc bài cơ bản về CAN tại đây :
http://www.picvietnam.com/forum/showthread.php?t=1804
và hãy đọc về họ dsPIC30F đặc biệt là phần về CAN
http://ww1.microchip.com/downloads/e...Doc/70046E.pdf
đừng quên đọc về em dsPIC30f0412 Và em MCP2551 nữa nhé
sau đó chúng ta sẽ tiếp tục làm việc....
(tôi mặc định là các bạn đã biết dùng MPLab C30)
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 12-02-2009, 10:46 AM   #2
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Phần cứng hết sức đơn giản nên tôi sẽ ko post lên nữa, bạn cứ nối TXD và RXD của dsPIC và MCP2551 lại với nhau, còn CANH và CANL của MCP2551 thì nối vào bus CANH và CANL là xong.
Phần thiết lập cấu hình cho CAN như sau:
Code:
// Init Can Protocol	
void init_can1(void)
{
//--------------------------------------------------------------------------------------------------------------------
					//Initialization of CAN1 Module and Enabling of CAN1 Interrupts
//--------------------------------------------------------------------------------------------------------------------

 
 
 C1CTRLbits.CANCKS = 1;			// Select the CAN Master Clock . It is equal to Fcy here. 
								// equal to Fcy.(Fcy=30Mhz)

 C1CFG1bits.SJW=00;				//Synchronized jump width time is 1 x TQ when SJW is equal to 00
 
 C1CFG1bits.BRP = BRP_VAL;		//((FCY/(2*NTQ*BITRATE))-1) 	

 C1CFG2 = 0x03F5;               // SEG1PH=6Tq, SEG2PH=3Tq, PRSEG=5Tq 
                                // Sample 3 times
                                // Each bit time is 15Tq

///Interrupt Section of CAN Peripheral

 C1INTF = 0;					//Reset all The CAN Interrupts 
 IFS1bits.C1IF = 0;  			//Reset the Interrupt Flag status register
 C1INTE = 0x00FF;               //Enable all CAN interrupt sources
 IEC1bits.C1IE = 1;				//Enable the CAN1 Interrupt 
//-----------------------------------------------------------------------------------------------------------------------
						// Configure Receive registers, Filters and Masks
//-----------------------------------------------------------------------------------------------------------------------

 // We are initializing the Receive Buffer 0 and Receive Buffer 1 for CAN1 

 
 C1RX0CON = C1RX1CON = 0x0000; 	// Receive Buffer1 and 0 Status
 														//and Control Register for CAN1 

 
 // Acceptance Mask Register0SID and Register1SID associated with Recieve Buffer0
 // and Receive Buffer1 for CAN1 
 C1RXM0SID  = C1RXM1SID  = 0x1FFD; 
 
 // Acceptance Mask Register0EIDH and Register1EIDH associated with Recieve Buffer0
 // and Receive Buffer1 for CAN1
 C1RXM0EIDH = C1RXM1EIDH = 0x0FFF; 

 // Acceptance Mask Register0EIDL and Register1EIDL associated with Recieve Buffer0 
 //and Receive Buffer1 for CAN1 and CAN2
 C1RXM0EIDL = C1RXM1EIDL = 0xFC00; 

 
//Initializing of Acceptance Filter n Standard Identifier for CAN1

 C1RXF0SID 	= 0x0AA8;	//CAN1 Receive Acceptance Filter0 SID 		
 C1RXF2SID 	= 0x1555;   //CAN1 Receive Acceptance Filter2 SID
 C1RXF2EIDH = 0x0004;   //CAN1 Receive Acceptace  Filter2 Extended Identifier high byte
 C1RXF2EIDL = 0x8C00;	//CAN1 Receive Acceptance Filter2 Extended identifier low byte
 
 //-----------------------------------------------------------------------------------------------------------------------
						// Configure Transmit Registers Buffer 0 and Transmit Buffer 1
//-----------------------------------------------------------------------------------------------------------------------
  
 C1TX0CON = 0x0003;     // High priority
 C1TX0SID = 0x50A8;     // SID 
 C1TX0EID = 0x0000;     // EID 
 C1TX0DLC = 0x01C0;		//Select the Data word Length for CAN1 Transmit Buffer0 which is 8 byte  
 
 
 
 C1TX1CON = 0x0002;             // High Intermediate priority
 C1TX1SID = 0xA855;             // SID  
 C1TX1EID = 0x0004;             // EID                   
 C1TX1DLC = 0x8DA0;				//Select the Data word Length for CAN1 Transmit Buffer1 which
								// is 4 byte

 C1CTRLbits.REQOP = 0; // nomal mode

 while(C1CTRLbits.OPMODE != 0);//Wait for CAN1 mode change

 
 //Enable transmission

 C1TX0CONbits.TXREQ = 1;        
 C1TX1CONbits.TXREQ = 1;
 C1CTRLbits.CANCAP=1;
}
để hiểu rõ hơn mong các bạn tham khảo lại trong dsPIC30F
Family Reference Manual phần các thanh ghi của CAN, nếu có gì chưa rõ, xin cứ đặt câu hỏi trực tiếp tại đây, ta sẽ cùng trao đổi
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 12-02-2009, 10:55 AM   #3
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
còn đây là code của chương trình main và xử lý ngắt của CAN
Code:
#include   <p30F4012.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL16)
;
_FWDT(WDT_OFF)
;
_FBORPOR(PBOR_OFF & MCLR_EN & PWMxL_ACT_HI & PWMxH_ACT_HI)
;
_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 		30000000             		// 30 MHz
#define BITRATE 	1000000			 			// 1Mbps
#define NTQ 		15							// Number of Tq cycles which will make the 
												//CAN Bit Timing .
#define BRP_VAL		((FCY/(2*NTQ*BITRATE))-1)  //Formulae used for C1CFG1bits.BRP 
#define BlueLed 	_LATE3
#define RedLed _LATE4
#define Switch _RE2
//---------------------------------------------------------------------
void init_can1(void);
void Init_ADC10(void);
// Buffer Registers for CAN data to be send out in the transmit mode.

unsigned int OutData0[4] = {0x5251, 0x5453, 0x5655, 0x5857};            
unsigned int OutData1[2] = {0x5A59, 0x5C5B};

// Intilializing the receive registers to be 0

unsigned int InData0[4] = {0x5251, 0x5453, 0x5655, 0x5857};
unsigned int InData1[2] = {0x5A59, 0x5C5B};

//---------------------------------------------------------------------
unsigned long BlueLedCounter=0;
unsigned int ADCValue;

int main(void)
{
 init_can1();
 // Init_ADC10();
 TRISD = 0x0000;				// Initialize the PORTD as output
 LATD = 0xFFFF;                 
 LATE = 0xffe7;
 TRISE = 0xFFe7; // LED noi vao E4 va E3
// Data Field 1,Data Field 2, Data Field 3, Data Field 4 // 8 bytes selected by DLC 

 C1TX0B1 = OutData0[0];
 C1TX0B2 = OutData0[1];
 C1TX0B3 = OutData0[2];
 C1TX0B4 = OutData0[3];
 //Data Field 1, Data Field 2 // 4 bytes selected by DLC

 C1TX1B1 = OutData1[0];
 C1TX1B2 = OutData1[1];
 while(1)
{
	BlueLedCounter++;
	if(BlueLedCounter>120000)
	{
			BlueLedCounter=0;
			if(Switch==0)
			{
				C1TX1B1 = OutData1[0];
 				C1TX1B2 = OutData1[1];
				C1TX1CONbits.TXREQ = 1;	
			}
			else{
				 C1TX0B1 = OutData0[0];
				 C1TX0B2 = OutData0[1];
				 C1TX0B3 = OutData0[2];
				 C1TX0B4 = OutData0[3];
				 C1TX0CONbits.TXREQ = 1;
			}		
	}

	
	                           
}	                            //end while loop


}	



//--------------------------------------------------------------------------------------------------------------------------
											//Interrupt Section for CAN1
//--------------------------------------------------------------------------------------------------------------------------

void __attribute__((interrupt, no_auto_psv)) _C1Interrupt(void)
{
      
		IFS1bits.C1IF = 0;         //Clear interrupt flag
	
      if(C1INTFbits.TX0IF)
      {
       
		 C1INTFbits.TX0IF = 0;  //If the Interrupt is due to Transmit0 of CAN1 Clear the Interrupt

      }  
      else if(C1INTFbits.TX1IF)
      {
        
		C1INTFbits.TX1IF = 0;   //If the Interrupt is due to Transmit1 of CAN1 Clear the Interrupt 

      }  

      if(C1INTFbits.RX0IF)
      {      
        
		C1INTFbits.RX0IF = 0; 	//If the Interrupt is due to Receive0 of CAN1 Clear the Interrupt

        InData0[0] = C1RX0B1; 
        InData0[1] = C1RX0B2;  	//Move the recieve data from Buffers to InData
        InData0[2] = C1RX0B3;	
        InData0[3] = C1RX0B4;

        if ((InData0[0]==OutData0[0]) && (InData0[1]==OutData0[1]) && (InData0[2]==OutData0[2]) && (InData0[3]==OutData0[3])) 
       
           	RedLed^=1;    	// If the data received is same which was transmitted 
                                  	
      }

      else if(C1INTFbits.RX1IF)
      {      
        
		C1INTFbits.RX1IF = 0;  	//If the Interrupt is due to Receive1 of CAN1 Clear the Interrupt
        InData1[0] = C1RX1B1;   //Move the data received to Indata Registers
        InData1[1] = C1RX1B2;

        //if ((InData1[0]==OutData1[0]) && (InData1[1]==OutData1[1])) 
       if(InData1[0]==0x5A59)
           BlueLed^=1;    //If the data received is same which was transmitted 
                                 
      }
		C1RX0CON = C1RX1CON = 0x0000;
}
trong này, tôi có định nghĩa 2 led để kiểm tra dữ liệu nhận được. chương trình này được nạp trực tiếp cho 2 chip 30f4012 giao tiếp thử nghiệm với nhau.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com

thay đổi nội dung bởi: hopeman, 12-02-2009 lúc 11:00 AM.
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 12-02-2009, 10:56 AM   #4
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
rất mong nhận được phản hồi và trao đổi cùng các bạn có quan tâm đến vấn đề này
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 05-03-2009, 11:43 AM   #5
silvadk2
Đệ tử 2 túi
 
Tham gia ngày: Nov 2008
Bài gửi: 42
:
Bạn ơi, bạn có thể viết tiếp ko, tôi cũng đang tìm hiểu về vấn đề này! Mong cả anh Namnq tham gia cho bọn em được nhờ !
silvadk2 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 05-03-2009, 04:19 PM   #6
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Trích:
Nguyên văn bởi silvadk2 View Post
Bạn ơi, bạn có thể viết tiếp ko, tôi cũng đang tìm hiểu về vấn đề này! Mong cả anh Namnq tham gia cho bọn em được nhờ !
bạn hãy thử copy code tôi để ở trên và chạy thử, bạn có thể hỏi đích danh phần nào ( trong Code hoặc vấn đề bạn thắc mắc) thì tôi còn biết để trả lời.nếu bạn bám sát các dòng code tôi đã up ở trên và các tài liệu tôi dẫn tới thì chắc là sẽ hiểu hết được thôi
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 09-03-2009, 10:37 PM   #7
silvadk2
Đệ tử 2 túi
 
Tham gia ngày: Nov 2008
Bài gửi: 42
:
uh, thank bạn nhiều nhiều. Cậu có thể nói dõ hơn cho mình là đoạn ctr chính thực hiện công việc cụ thể gì không ? với cái phần cứng thì có cần điện trở định thiên và mạch xén đỉnh không ? Bài viết của bạn đã giúp mình rất nhiều !
silvadk2 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 10-03-2009, 01:55 PM   #8
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
if(BlueLedCounter>120000)
{
BlueLedCounter=0;
if(Switch==0)
{
C1TX1B1 = OutData1[0];
C1TX1B2 = OutData1[1];
C1TX1CONbits.TXREQ = 1;
}
else{
C1TX0B1 = OutData0[0];
C1TX0B2 = OutData0[1];
C1TX0B3 = OutData0[2];
C1TX0B4 = OutData0[3];
C1TX0CONbits.TXREQ = 1;
}
}
chương trình chính của mình rất đơn giản là cứ sau khoảng 1/2s thì đưa dữ liệu vào bộ đệm
C1TX1B1 = OutData1[0];
C1TX1B2 = OutData1[1];
và yêu cầu truyền
C1TX1CONbits.TXREQ = 1;
còn câu hỏi còn lại của bạn mình ko hiểu lắm.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 19-03-2009, 12:41 AM   #9
bin7
Nhập môn đệ tử
 
Tham gia ngày: Oct 2008
Bài gửi: 4
:
em cung dang tim hieu ve mang CAN, cho e hoi dinh nghia nay trong Code
#define Switch _RE2
bin7 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 19-03-2009, 01:06 AM   #10
bin7
Nhập môn đệ tử
 
Tham gia ngày: Oct 2008
Bài gửi: 4
:
Question

Switch quyết định dùng Buffer truyền 0(Dữ liệu được nạp có độ dài 8 byte) hoặc Buffer1(4 Byte) .Sau khi Frame dữ liệu được truyền thành công thì xảy ra một ngắt.Tại chương trình xử lý ngắt , dspic nhận tin và nếu tin nhắn được nhận vào Buffer 0 thì đèn red sáng ,còn được nhận và Buffer 1 thì đèn blue sang. Vậy theo chương trình của a ,sau khi chạy thì cứ sau khoảng 1/2s thì tương ứng với mỗi vi điều khiển lại có một đèn sáng(đỏ hoặc xanh) đúng không ạ!
bin7 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 19-03-2009, 11:18 PM   #11
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Wink

Trích:
Nguyên văn bởi bin7 View Post
Switch quyết định dùng Buffer truyền 0(Dữ liệu được nạp có độ dài 8 byte) hoặc Buffer1(4 Byte) .Sau khi Frame dữ liệu được truyền thành công thì xảy ra một ngắt.Tại chương trình xử lý ngắt , dspic nhận tin và nếu tin nhắn được nhận vào Buffer 0 thì đèn red sáng ,còn được nhận và Buffer 1 thì đèn blue sang. Vậy theo chương trình của a ,sau khi chạy thì cứ sau khoảng 1/2s thì tương ứng với mỗi vi điều khiển lại có một đèn sáng(đỏ hoặc xanh) đúng không ạ!
chính xác là như thế , dòng đó đơn giản chỉ là định nghĩa ngõ vào cho 1 cái công tắc thôi.và có lẽ là bạn đã hiểu được hết chương trình mình viết rồi đấy.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 20-03-2009, 03:07 AM   #12
bin7
Nhập môn đệ tử
 
Tham gia ngày: Oct 2008
Bài gửi: 4
:
Trước hết em thay mặt những ngừơi lười cảm ơn anh rất nhiều, không có a không biết phải mò đến bao giờ!

Trong chương trình khởi tạo CAN ,khi khởi tạo bộ đệm 0 và 1 a khởi tạo là
C1RX0CON = C1RX1CON = 0x0000;
Như vậy bit FILHIT của hai thanh ghi trên đều xác lập cho phép bộ loc 0,và khi khởi tạo cho bộ lọc:
C1RXF0SID = 0x0AA8; //CAN1 Receive Acceptance Filter0 SID
C1RXF2SID = 0x1555; //CAN1 Receive Acceptance Filter2 SID
C1RXF2EIDH = 0x0004; //CAN1 Receive Acceptace Filter2 Extended Identifier high byte
C1RXF2EIDL = 0x8C00; //CAN1 Receive Acceptance Filter2 Extended identifier low byte
tại sao lại sử dụng cả bộ lọc 2 ,em nghĩ bit DBEN khi được set sử dụng luôn bộ lọc 0 cho bộ đệm 1?

Tiện thể a có thể nói rõ hơn một chút về chức năng của bộ lọc và mặt nạ được ko, e có đọc qua tài liệu nhưng hãy còn mơ hồ quá?
Cảm ơn a rất nhiều!
bin7 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 20-03-2009, 05:45 PM   #13
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Bạn hãy xem sơ đồ cấu trúc của Can trong tài liệu về dòng 30F http://ww1.microchip.com/downloads/e...Doc/70046E.pdf của Pic hình 23-8
Filter 0 và 1 dùng để lọc và cho vào RX0, còn 2,3,4,5 là dùng để lọc cho vào RX1 ( như thế có nghĩa là cùng lúc có thể tồn tại 2 bộ lọc trên 1 pic, bộ lọc này chính là so sánh đoạn đầu của frame dữ liệu gửi tới để xem có cho vào bộ đệm nhận RX và sinh ngắt hay không, bạn nên đọc lại bài cơ bản về Can đã có link ở phần đầu để hiểu rõ hơn nhé.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-03-2009, 12:15 AM   #14
bin7
Nhập môn đệ tử
 
Tham gia ngày: Oct 2008
Bài gửi: 4
:
Talking

A cho em hỏi,chỉ xét đến bộ đệm nhận và bộ đệm truyền 0 cho đơn giản nhé!A chọn mặt nạ là 23 bit 1
C1RXM0SID = 0x1FFD;
C1RXM0EIDH = 0x0FFF;
C1RXM0EIDL = 0xFC00;
, tức là bộ lọc 0 sẽ xét toàn bộ 23 bit của ID tin nhận đến
Bộ lọc trùng với ID ,data sẽ được đưa vào bộ đệm 0.Vậy e không muốn tin này nhận được theo trương trình của a e chỉ việc thay đổi thanh ghi này đúng không?
C1RXF0SID = 0x0AA8; //CAN1 Receive Acceptance Filter0 SID
Ví dụ thành:C1RXF0SID = 0x0AAA;

Em hỏi thế vì hình như e thay đổi thanh ghi này Dữ liệu vẫn được nhận."dữ liệu sau đó được e truyền lên qua UART"
bin7 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 26-06-2009, 04:28 PM   #15
hopeman
Đệ tử 6 túi
 
hopeman's Avatar
 
Tham gia ngày: Jul 2007
Bài gửi: 146
:
Xin lỗi vì lâu tôi không để ý, tưởng là chưa có ai quan tâm vấn đề này nên chưa trả lời câu hỏi trên cho bạn.
thứ nhất, tôi đang dùng ở chế độ nhận cơ bản ( standard data frame) nên là sẽ có mặt nạ là 11 bit.
"Bộ lọc trùng với ID ,data sẽ được đưa vào bộ đệm 0.Vậy e không muốn tin này nhận được theo trương trình của a e chỉ việc thay đổi thanh ghi này đúng không?"
Tôi cho rằng bạn chưa thực sự hiểu sự khác biệt giữa mặt nạ và bộ lọc . bộ lọc thì để lọc còn mặt nạ là cái cho phép lọc ở những bit nào. bạn hãy tham khảo thêm mục 23.6.2 Message Acceptance Filters trang 674 của tài liệu dsPIC30F Family Reference Manual để hiểu rõ hơn nhé.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com
hopeman vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Trả lời


Quyền Sử Dụng Ở Diễn Ðàn
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is Mở
Smilies đang Mở
[IMG] đang Mở
HTML đang Tắt

Chuyển đến


Múi giờ GMT. Hiện tại là 02:25 PM.


Được sáng lập bởi Đoàn Hiệp
Powered by vBulletin®
Page copy protected against web site content infringement by Copyscape
Copyright © PIC Vietnam