Thông báo

Collapse
No announcement yet.

Giao thức TCP/IP và Web server với AVR

Collapse
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #46
    Mọi người thấy chỗ nào chưa rõ ràng thì cứ hỏi nhé. Việc lập trình đòi hỏi phải hiểu rất rõ hoạt động của giao thức, hiểu rõ đến từng bit của bản tin, không giống như học để hiểu nguyen tắc làm việc.
    Ví dụ như tôi chẳng hạn, mặc dù đã từng dạy về giao thức TCP/IP, cứ nghĩ là mình đã hiểu rõ giao thức lắm rồi, nhưng khi bắt tay vào viết code, gặp lỗi phải debug từng byte, thậm chí từng bit của từng gói tin, thì mới phát hiện ra là mình còn chưa hiểu gì cả.
    Học để biết và học để làm được là một khoảng cách khá xa.
    Last edited by nttam79; 07-11-2011, 10:37.

    Comment


    • #47
      Để thay đổi không khí tí. Hôm trước mình đã nói là nếu viết xong giao thức ICMP, chưa cần TCP và UDP, thì đã có thể ping được tới board mạch của chúng ta. Từ đầu đến giờ chúng ta viết code quá trời luôn mà chưa thể nạp vào chip để chạy thử 1 cái, kể cũng hơi nản. Vậy tới đây mình dừng lại để hướng dẫn bổ sung một số hàm và viết hàm main() trong file “ntAVRnet.c” để có thể biên dịch nạp vào chip Atmega32, sau đó ta sẽ thử ping tới mạch xem mạch của ta đã hoạt động chưa nhé.

      Đầu tiên, ta phải viết một số hàm mà từ đầu đến giờ ta vẫn chưa viết: đó là hàm printf sử dụng uart để xuất thông tin lên cổng COM trên máy tính và ngắt cho timer.

      Phần này sẽ không giải thích chi tiết vì không phải là trọng tâm chính, các bạn tự tìm hiểu nhé:
      Thêm vào project cặp file “uart.c” và “uart.h”
      Nội dung file “uart.c”:
      Code:
      //----------------------------------------------------------------------------
      // Writen by NTTam - PTITHCM
      //----------------------------------------------------------------------------
      #include <avr/io.h>
      #include <avr/pgmspace.h>
      #include <avr/interrupt.h>
      #include <stdarg.h>
      #include "ntAVRnet.h"
      #include "uart.h"
      //----------------------------------------------------------------------------
      char UartRxBuffer[UART_RX_BUFFER_SIZE];
      char UartTxBuffer[UART_TX_BUFFER_SIZE];
      volatile unsigned char UartTxBufferStart;
      volatile unsigned char UartTxBufferLen;
      volatile unsigned char UartRxBufferStart;
      volatile unsigned char UartRxBufferLen;
      static char HexTable[] PROGMEM= "0123456789ABCDEF";
      //----------------------------------------------------------------------------
      void uartInit(unsigned long baudrate)
      {
      	unsigned int bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);//
      	UBRRL = bauddiv;
      	#ifdef UBRRH
      	UBRRH = ((bauddiv>>8) & 0x0F);
      	// URSEL   7
      	// UMSEL   6	0:Asynchronuos/1:Synchronous
      	// UPM1    5	Parity mode: 00:disabled/01:Reserved/10:Even/11:Odd
      	// UPM0    4	
      	// USBS    3	Stop bit: 0:1 bit/1:2 bit
      	// UCSZ1   2	Char size:000:5/001:6/010:7/011:8/111:9/others:reserverd
      	// UCSZ0   1
      	// UCPOL   0
      	UCSRC = 0x80 | (1<<UCSZ1) | (1<<UCSZ0);
      	#endif
      	UCR =((1 << TXEN) | (1 << RXEN) | (1<< RXCIE) | (1<< TXCIE));// 
      	UartTxBufferStart = 0;
      	UartTxBufferLen = 0;
      	UartRxBufferStart = 0;
      	UartRxBufferLen = 0;
      	sei();
      }
      //--------------------------------------------------------------------------------------
      SIGNAL(SIG_UART_TRANS)
      {
      	if(UartTxBufferLen){
      		--UartTxBufferLen;
      		UDR = UartTxBuffer[UartTxBufferStart++];
      		if (UartTxBufferStart == UART_TX_BUFFER_SIZE)
         			UartTxBufferStart = 0;
      	}
      }
      //--------------------------------------------------------------------------------------
      SIGNAL(SIG_UART_RECV)
      {
      	unsigned char i;
      	char status,data;
      	status = USR;
      	data = UDR;
      	if ((status & ((1<<FE) | (1<<PE) | (1<<DOR))) == 0){
      		if(++UartRxBufferLen == UART_RX_BUFFER_SIZE)
      			UartRxBufferLen = UART_RX_BUFFER_SIZE;
      		i = UartRxBufferStart+UartRxBufferLen;	//Vi tri ky tu cuoi cung trong buffer
      		if(i > UART_RX_BUFFER_SIZE)
      			i -= UART_RX_BUFFER_SIZE;
      		UartRxBuffer[i-1] = data;
      	}
      }
      //--------------------------------------------------------------------------------------
      char uartGetByte(void)
      {
      	//
      	char c;
      	if(UartRxBufferLen){
      		UartRxBufferLen--;
      		c = UartRxBuffer[UartRxBufferStart++];
      		if(UartRxBufferStart == UART_RX_BUFFER_SIZE)
      			UartRxBufferStart = 0;
      		return(c);
      	}
      	return(-1);
      }
      //--------------------------------------------------------------------------------------
      void uartSendByte(char c)
      {
      	unsigned char i;
      	if((USR & (1<<UDRE)) && (UartTxBufferLen == 0)){	//Neu uart dang san sang va buffer trong
      		UDR = c;			//Gui luon
      	}else{
      		//Neu uart dang ban
      		while(UartTxBufferLen == UART_TX_BUFFER_SIZE);	//Cho neu buffer dang day
      		i = UartTxBufferStart + UartTxBufferLen;
      		UartTxBufferLen++;
      		if(i >= UART_TX_BUFFER_SIZE)
      			i -=UART_TX_BUFFER_SIZE;
      		UartTxBuffer[i] = c;	//Ghi vao cuoi buffer
      	}
      }
      //--------------------------------------------------------------------------------------
      int printfP(const prog_char *format, ...)
      {
      	// simple printf routine
      	// define a global HexChars or use line below
      	//static char HexChars[16] = "0123456789ABCDEF";
      	char c;
      	unsigned int u_val, div_val, base;
      	va_list ap;
      	va_start(ap, format);
      	for (;;)
      	{
      		while ((c = pgm_read_byte(format++) ) != '%')
      		{	// Until '%' or '\0'
      			if (!c)
      			{
      				va_end(ap);
      				return(0);
      			}
      			uartSendByte(c);
      		}
      
      		switch (c = pgm_read_byte(format++) )
      		{
      			case 'c': c = va_arg(ap,int);
      			default:  uartSendByte(c); continue;
      			case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
      //			case 'x': base = 16; div_val = 0x10;
      			case 'x': base = 16; div_val = 0x1000;
      
      			CONVERSION_LOOP:
      			u_val = va_arg(ap,int);
      			if (c == 'd')
      			{
      				if (((int)u_val) < 0)
      				{
      					u_val = - u_val;
      					uartSendByte('-');
      				}
      				while (div_val > 1 && div_val > u_val) div_val /= 10;
      			}
      			do
      			{
      				//c =pgm_read_byte(HexTable+(u_val/div_val));
      				uartSendByte(pgm_read_byte(HexTable+(u_val/div_val)));
      				u_val %= div_val;
      				div_val /= base;
      			} while (div_val);
      		}
      	}
      	va_end(ap);
      }
      //--------------------------------------------------------------------------------------
      Nội dung file “uart.h”:
      Code:
      //----------------------------------------------------------------------------
      // Writen by NTTam - PTITHCM
      //----------------------------------------------------------------------------
      #ifndef UART_H
      #define UART_H
      
      #include <avr/pgmspace.h>
      //----------------------------------------------------------------------------
      #define UART_TX_BUFFER_SIZE		8
      #define UART_RX_BUFFER_SIZE		8
      //--------------------------------------------------------------------------------------
      #ifndef UART_INTERRUPT_HANDLER
      #define UART_INTERRUPT_HANDLER	SIGNAL
      #endif
      //define for ATmega32 register
      #define USR UCSRA
      #define UCR UCSRB
      #define UBRR UBRRL
      #define EICR EICRB
      #define USART_RX USART_RXC_vect  
      #define USART_TX USART_TXC_vect  
      //--------------------------------------------------------------------------------------
      void uartInit(unsigned long baudrate);
      char uartGetByte();
      void uartSendByte(char c);
      int printfP(const prog_char *format, ...);
      #define printf(format, args...) printfP(PSTR(format), ## args)
      //--------------------------------------------------------------------------------------
      #endif //UART_H
      Tiếp tục hêm vào project cặp file “timer.c” và “ timer.h”
      Nội dung file “ timer.c”:
      Code:
      //----------------------------------------------------------------------------
      // Writen by NTTam - PTITHCM
      //----------------------------------------------------------------------------
      #include <avr/io.h>
      #include <avr/interrupt.h>
      #include "ntAVRnet.h"
      #include "timer.h"
      #include "ethernet.h"
      #include "arp.h"
      //#include "tcp.h"
      //----------------------------------------------------------------------------
      extern volatile unsigned int time_watchdog;
      static volatile unsigned long UptimeMs;
      static volatile unsigned char Counter10ms;
      static volatile unsigned int Counter1s;
      //----------------------------------------------------------------------------
      void timer1Init(void)
      {
      	// initialize timer 1
      	// set prescaler on timer 1
      	TCCR1B = (TCCR1B & ~TIMER_PRESCALE_MASK) | TIMER1PRESCALE;	// set prescaler
      	TCNT1H = 0;						// reset TCNT1
      	TCNT1L = 0;
      	TIMSK |= (1<<TOIE1);						// enable TCNT1 overflow
      	TCNT1 = 0xFFFF - TIMER1_INTERVAL;
      }
      void timerInit(void)
      {
      	timer1Init();
      	sei();
      }
      //! Interrupt handler for tcnt1 overflow interrupt
      TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
      {
      	//Tai nap gia tri timer 1
      	TCNT1 = 0xFFFF - TIMER1_INTERVAL;
      	//Cap nhat watchdog timer
      	if((time_watchdog++) > 120){
              time_watchdog = 0;
              ethInit();
      	}
      	Counter1s++;
      	arpTimer();
      	//TCPCheckTimeOut();
      }
      Nội dung file “ timer.h”:
      Code:
      //----------------------------------------------------------------------------
      // Writen by NTTam - PTITHCM
      //----------------------------------------------------------------------------
      #ifndef TIMER_H
      #define TIMER_H
      //----------------------------------------------------------------------------
      #define TIMER_CLK_STOP			0x00	///< Timer Stopped
      #define TIMER_CLK_DIV1			0x01	///< Timer clocked at F_CPU
      #define TIMER_CLK_DIV8			0x02	///< Timer clocked at F_CPU/8
      #define TIMER_CLK_DIV64			0x03	///< Timer clocked at F_CPU/64
      #define TIMER_CLK_DIV256		0x04	///< Timer clocked at F_CPU/256
      #define TIMER_CLK_DIV1024		0x05	///< Timer clocked at F_CPU/1024
      #define TIMER_CLK_T_FALL		0x06	///< Timer clocked at T falling edge
      #define TIMER_CLK_T_RISE		0x07	///< Timer clocked at T rising edge
      #define TIMER_PRESCALE_MASK		0x07	///< Timer Prescaler Bit-Mask
      
      #define TIMER1PRESCALE		TIMER_CLK_DIV64		///< timer 1 prescaler default
      
      #ifndef TIMER_INTERRUPT_HANDLER
      #define TIMER_INTERRUPT_HANDLER		SIGNAL
      #endif
      void timer1Init(void);
      void timerInit(void);
      
      
      #endif //TIMER_H
      Mục đích chính của timer ở đây là ta tạo ra ngắt (ở đây dùng timer 1, các bạn dùng timer nào cũng được), để gọi hàm kiểm tra timeout và cập nhật watchdog timer.

      Thêm define vào ntAVRnet.h
      Code:
      #define TIMER_PRESCALE		1024
      #define TIMER1_INTERVAL		(F_CPU/TIMER_PRESCALE)
      
      #define IPDOT(a,b,c,d)	((unsigned long)((unsigned char)a)<<24)+((unsigned long)((unsigned char)b)<<16)+((unsigned long)((unsigned char)c)<<8)+(unsigned char)d//((a<<24)|(b<<16)|(c<<8)|(d))
      #define IPADDRESS			IPDOT(192,168,1,10)
      #define NETMASK				IPDOT(255,255,255,0)
      #define GATEWAY				IPDOT(192,168,1,1)
      
      #define ETHADDR0	'0'
      #define ETHADDR1	'F'
      #define ETHADDR2	'F'
      #define ETHADDR3	'I'
      #define ETHADDR4	'C'
      #define ETHADDR5	'E'
      Thêm include vào “ethernet.c” để từ đó có thể gọi các hàm của giao thức ip và arp:
      Code:
      #include "arp.h"
      #include "ip.h"
      Thêm include vào file “ip.c”:
      Code:
      #include "icmp.h"
      #include "uart.h"
      Và thêm thêm // vào trước lệnh gọi hàm UDPProcess, TCPProcess trong hàm IPProcess (vì ta vẫn chưa viết 2 hàm này của giao thức UDP và TCP).

      Mở “ntAVRnet.c”:
      Thêm hàm khởi động các dịch vụ mạng:
      Code:
      void netInit(unsigned long ipaddress, unsigned long netmask, unsigned long gatewayip)
      {
      	// init network device driver
      	#ifdef NET_DEBUG
      	printf("Initializing Network Device\r\n");
      	#endif
      	ethInit();
      	// init ARP
      	#ifdef NET_DEBUG
      	printf("Initializing ARP cache\r\n");
      	#endif
      	arpInit();
      	// init addressing
      	#ifdef NET _DEBUG
      	printf("Initializing Addressing\r\n");
      	#endif
      	ipSetConfig(ipaddress, netmask, gatewayip);
      	//dhcpInit();
      	//TCPInit();
      	//httpInit();
      
      }
      Hàm xuất ra cổng serial các thông tin cấu hình IP:
      Code:
      //--------------------------------------------------------------------------------------
      void	PrintIPConfig()
      {
      	printf("MAC Address: ");		ethPrintAddr(&IpMyConfig.ethaddr);		printf("\n\r");
      	printf("IP  Address: ");		ipPrintAddr(IpMyConfig.ip);				printf("\n\r");
      	printf("Subnet Mask: ");		ipPrintAddr(IpMyConfig.netmask);		printf("\n\r");
      	printf("Default Gateway: ");	ipPrintAddr(IpMyConfig.gateway);		printf("\n\r");
      }
      Để hàm này có thể truy xuất biến IpMyConfig nằm trong module “ip.c”, ta thêm dòng khai báo sau vào đầu file “ntAVRnet.c”.
      Code:
      extern struct ipConfig IpMyConfig;
      Và viết hàm khởi động hệ thống:
      Code:
      //--------------------------------------------------------------------------------------
      void	SystemInit()
      {
      	timerInit();
      	uartInit(UART_BAUDRATE);
      }
      Và cuối cùng là viết hàm main():
      Code:
      int		main(void)
      {
      	SystemInit();
      	printf("\r\nNTTam AVR network testing with enc28j60.\r\n");
      	printf("Initializing Network Interface and Stack\r\n");
      	printf("Ethernet chip init\r\n");
      	IpMyConfig.ethaddr.addr[0] = ETHADDR0;
      	IpMyConfig.ethaddr.addr[1] = ETHADDR1;
      	IpMyConfig.ethaddr.addr[2] = ETHADDR2;
      	IpMyConfig.ethaddr.addr[3] = ETHADDR3;
      	IpMyConfig.ethaddr.addr[4] = ETHADDR4;
      	IpMyConfig.ethaddr.addr[5] = ETHADDR5;
      	IpMyConfig.ip = IPADDRESS;
      	IpMyConfig.netmask = NETMASK;
      	IpMyConfig.gateway = GATEWAY;
      	netInit(IpMyConfig.ip, IpMyConfig.netmask, IpMyConfig.gateway);
      	PrintIPConfig();
      	while(1)
      	{
      		ethService();
      	}
      	return 0;}
      Biên dịch, nạp chip và thử gõ lệnh « ping 192.168.1.10 » xem sao.
      Địa chỉ IP, Subnet và gateway các bạn có thể thay đổi ở các define trong file « ntAVRnet.h » cho phù hợp với mạng ở nhà mình nhé.

      Comment


      • #48
        Để giúp mọi người làm mạch, mình post thêm file mạch in mà mình đã làm:
        AEC32_VER1_1.zip

        Hầu hết linh kiện có thể mua tại Trang chủ - Thiên Minh Electronic Solutions
        Danh sách LK và giá tham khảo:
        Last edited by nttam79; 07-11-2011, 16:40. Lý do: post nhầm file ảnh

        Comment


        • #49
          Thầy giải thích dÙm em cái hàm ipchecksum.Em tưởng check sum là cộng từng byte dữ liệu lại thôi.Sao mà lại có cái while lạ thế.
          , , ,

          Comment


          • #50
            Nguyên văn bởi rptdnmqs Xem bài viết
            Thầy giải thích dÙm em cái hàm ipchecksum.Em tưởng check sum là cộng từng byte dữ liệu lại thôi.Sao mà lại có cái while lạ thế.
            Hehe, bởi vậy, lúc viết code chỗ này tôi cũng tưởng vậy, cứ nghĩ là mình biết rồi, té ra là chưa biết gì cả (hay nói chính xác hơn là biết chưa tới). Nguyên nhân là thế này:
            - Đúng là checksum là cộng lại nhưng:
            1-Cộng từng word (16 bit) chứ không phải từng byte
            2-Checksum IP được quy định là: "bù-1 16 bit của tổng bù-1 của tất của các từ 16 bit trong header IP".
            Nghe hơi khó hiểu, cụ thể là thế này:
            - Đầu tiên ta cộng các từ 16 bit trong header:
            Code:
                for (;;) {
                    if (len < 2)
                        break;
            		sum += *((unsigned int *)data);
            		data+=2;
                    len -= 2;
                }
            Nên nhớ data là biến con trỏ đến kiểu char, vì vậy ta ép kiểu nó sang biến con trỏ kiểu int: (unsigned int *)data và lấy giá trị tại địa chỉ con trỏ thì được số 16 bit: *((unsigned int *)data). Tiếp theo ta tăng biến con trỏ thêm 2 byte và trừ len đi 2 byte. Lặp đến khi nào số byte còn lại nhỏ hơn 2.
            Đến đây, nếu số byte là chẵn, len=0, nếu số byte lẻ (chia từng cặp 2 byte còn thừa lại 1 byte) thì len=1. Ta cộng nốt byte đó vào (xem nó như là 1 từ 2 byte mà byte cao bằng 0x00):
            Code:
                if (len)//Tuc la len=1, con thua 1 byte
                    sum += *(unsigned char *) data;
            Như vậy là ta tính tổng của header xong, nhưng nên nhớ khi cộng như vậy trong AVR, kết quả sẽ là tổng bù-2 chứ không phải tổng bù-1 như yêu cầu.
            Để chuyển tổng bù-2 sang bù-1, ta cần cộng phần dư vào, chính vì lý do này mà ta khai báo biến sum là biến long, có chiều dài 4 byte, hai byte cao của nó chứa phần dư.
            Code:
                while ((len = (unsigned int) (sum >> 16)) != 0)
                    sum = (unsigned int) sum + len;
            Ở đây ta gán len=(unsigned int) (sum >> 16) chính là 2 byte cao của biến 4 byte sum, lúc này biến len được tận dụng như là 1 biến tạm thôi, không có ý nghĩa là chiều dài nữa.
            Ta đem phần dư (2 byte cao, được chứa trong biến len) cộng với 2 byte thấp: (unsigned int) sum (phải ép kiểu sum từ long sang int nếu không nó sẽ cộng cả 4 byte của sum).
            Vòng lặp này cho đến khi nào 2 byte cao của sum=0x0000 (hết phần dư).
            Vậy kết quả ta thu được bây giờ là :"tổng bù-1 của tất của các từ 16 bit trong header IP".
            Cuối cùng ta cần lấy bù-1 của kết quả này, đó là checksum IP.
            Code:
                return (unsigned int) sum ^ 0xFFFF;
            Phức tạp chưa. Đã nói là khi viết phần này tôi mất 4h chỉ để sửa hàm checksum và debug các gói IP để xem mình sai chỗ nào. Em thắc mắc cũng không có gì lạ.
            Last edited by nttam79; 08-11-2011, 12:36. Lý do: Chú thích rõ hơn các câu lệnh

            Comment


            • #51
              Hôm nay mần được cái mạch rùi, test được LCD. Chờ anh Tâm hoàn thành bài viết rồi test luôn tổng thể. Các bạn có thể ủi mạch và làm theo để bài viết của anh Tâm thêm phần hấp dẫn nha.
              Có mấy cái hình post lên anh em chấm điểm
              Click image for larger version

Name:	P1010018 (FILEminimizer).JPG
Views:	1
Size:	118.7 KB
ID:	1353553
              Click image for larger version

Name:	P1010023 (FILEminimizer).JPG
Views:	1
Size:	93.8 KB
ID:	1353554
              Click image for larger version

Name:	P1010025 (FILEminimizer).JPG
Views:	1
Size:	88.0 KB
ID:	1353555

              Email:
              Tel: 0983.497.310

              Comment


              • #52
                Nguyên văn bởi nttam79
                Mạch ủi tay mà được như vậy là quá đẹp , anh không bao giờ ủi được như vậy hết, toàn phải đi đặt mạch in.
                em chưa làm mạch ngay mà mô phỏng trên proteus đã
                ko bit lúc trc thầy có mô phỏng ko?hay làm thực tế luôn
                em thấy thằng Pic có 2 ví dụ mô phỏng trong proteus rất hay,có cả webserver nữa, nên muốn mô phỏng qua mega32 xem thế nào mà chưa dc
                khi mô xong rùi, post lên mọi người cùng xem
                P/S: mạch bác đẹp thật đấy, dây bé tí, em mà vẽ là dây phải to ủi mới thích, bóc giấy ko sợ đứt
                hình như bác chưa quét nhựa thông, em ko thấy, quét vô, để trong tủ kính, mấy năm sau bỏ ra vẫn thấy như mới.
                Thầy xem tham số: UART_BAURATE chưa define thì phải?

                Comment


                • #53
                  Nguyên văn bởi hieppro89 Xem bài viết
                  em chưa làm mạch ngay mà mô phỏng trên proteus đã
                  ko bit lúc trc thầy có mô phỏng ko?hay làm thực tế luôn
                  em thấy thằng Pic có 2 ví dụ mô phỏng trong proteus rất hay,có cả webserver nữa, nên muốn mô phỏng qua mega32 xem thế nào mà chưa dc
                  khi mô xong rùi, post lên mọi người cùng xem
                  P/S: mạch bác đẹp thật đấy, dây bé tí, em mà vẽ là dây phải to ủi mới thích, bóc giấy ko sợ đứt
                  hình như bác chưa quét nhựa thông, em ko thấy, quét vô, để trong tủ kính, mấy năm sau bỏ ra vẫn thấy như mới.
                  Thầy xem tham số: UART_BAURATE chưa define thì phải?
                  Lúc trước tôi không mô phỏng, mà nói chung trước giờ hiếm khi nào mô phỏng trước khi làm mạch, vì mạch phức tạp thì việc mô phỏng không có nhiều ý nghĩa, mà mạch đơn giản thì cần gì phải mô phỏng, chỉ mô phỏng mạch analog thôi.
                  Đúng là tôi quên mất define thông số này, các bạn thêm vào, tốc độ tùy mọi người thôi. Ví dụ:
                  Code:
                  #define  UART_BAURATE  9600l
                  Last edited by nttam79; 09-11-2011, 11:40.

                  Comment


                  • #54
                    Thầy và mọi người trên diễn đàn, cho hỏi câu này: Em bị lỗi debug như hình. Có kiếm trên mạng cách sửa(edit include), có sửa lỗi được kha khá, but cái thằng lỗi này tưởng na lá với các lỗi khác, mà lại không sửa được. Mong mọi người chỉ giúp!
                    Click image for larger version

Name:	debug.jpg
Views:	1
Size:	73.8 KB
ID:	1353593

                    Comment


                    • #55
                      Nguyên văn bởi dinh_dong Xem bài viết
                      Thầy và mọi người trên diễn đàn, cho hỏi câu này: Em bị lỗi debug như hình. Có kiếm trên mạng cách sửa(edit include), có sửa lỗi được kha khá, but cái thằng lỗi này tưởng na lá với các lỗi khác, mà lại không sửa được. Mong mọi người chỉ giúp!
                      [ATTACH=CONFIG]35158[/ATTACH]
                      Lỗi đó có nghĩa là kiểu struct APentry được định nghĩa 2 lần.
                      Lỗi này thường phát sinh do file arp.h được include 2 lần vào 1 file code. Chính vì vậy mà trong mỗi file header, tôi đều thêm vào đầu file:
                      Code:
                      #ifndef ARP_H
                      #define ARP_H
                      và cuối file:
                      Code:
                      #endif //ARP_H
                      Các dòng này nhằm mục đích nếu file được include nhiều hơn 1 lần, thì các lần sau nó sẽ được bỏ qua (vì điều kiện #ifndef ARP_H sẽ false, do ARP_H đã được định nghĩa trước đó.
                      Còn 1 lý do có thể dẫn đến lỗi này là do khai báo trùng APentry ở đâu đó (ít có khả năng xảy ra).
                      Nếu tìm không ra lỗi, em có thể gửi toàn bộ code lên DĐ hay qua mail, tôi sẽ check cho.

                      Comment


                      • #56
                        Nguyên văn bởi dinh_dong Xem bài viết
                        Thầy và mọi người trên diễn đàn, cho hỏi câu này: Em bị lỗi debug như hình. Có kiếm trên mạng cách sửa(edit include), có sửa lỗi được kha khá, but cái thằng lỗi này tưởng na lá với các lỗi khác, mà lại không sửa được. Mong mọi người chỉ giúp!
                        [ATTACH=CONFIG]35158[/ATTACH]
                        bác phải post cả project lên chứ
                        lỗi cái này thì lại liên quan tới cái kia mà
                        nhưng nhìn vào dòng :"redefinition of...." thì theo em là: bác đã định nghĩa cấu trúc ARpentry ở header khác rồi, bây giờ định nghĩa lại thì nó báo " redefinition" tức là lỗi "định nghĩa lại" bác thử kiểm tra lại xem, không bằng chi post lên cho mọi người xem
                        em debug ok rồi, mà mô phỏng = proteus,hiển thị lên terminal toàn kí tự Ai Cập thôi, he he

                        Comment


                        • #57
                          Nguyên văn bởi hieppro89 Xem bài viết
                          bác phải post cả project lên chứ
                          em debug ok rồi, mà mô phỏng = proteus,hiển thị lên terminal toàn kí tự Ai Cập thôi, he he
                          Xem lại baudrate, set fulse cho system clock, tần số thạch anh, các define tốc độ CPU.

                          Comment


                          • #58
                            Nguyên văn bởi hieppro89 Xem bài viết
                            bác phải post cả project lên chứ
                            lỗi cái này thì lại liên quan tới cái kia mà
                            nhưng nhìn vào dòng :"redefinition of...." thì theo em là: bác đã định nghĩa cấu trúc ARpentry ở header khác rồi, bây giờ định nghĩa lại thì nó báo " redefinition" tức là lỗi "định nghĩa lại" bác thử kiểm tra lại xem, không bằng chi post lên cho mọi người xem
                            em debug ok rồi, mà mô phỏng = proteus,hiển thị lên terminal toàn kí tự Ai Cập thôi, he he
                            Nguyên văn bởi nttam79 Xem bài viết
                            Lỗi đó có nghĩa là kiểu struct APentry được định nghĩa 2 lần.
                            Lỗi này thường phát sinh do file arp.h được include 2 lần vào 1 file code. Chính vì vậy mà trong mỗi file header, tôi đều thêm vào đầu file:
                            Code:
                            #ifndef ARP_H
                            #define ARP_H
                            và cuối file:
                            Code:
                            #endif //ARP_H
                            Các dòng này nhằm mục đích nếu file được include nhiều hơn 1 lần, thì các lần sau nó sẽ được bỏ qua (vì điều kiện #ifndef ARP_H sẽ false, do ARP_H đã được định nghĩa trước đó.
                            Còn 1 lý do có thể dẫn đến lỗi này là do khai báo trùng APentry ở đâu đó (ít có khả năng xảy ra).
                            Nếu tìm không ra lỗi, em có thể gửi toàn bộ code lên DĐ hay qua mail, tôi sẽ check cho.
                            Debug Code cũng hay, em muốn tự làm, tìm ra được lỗi có cảm giác thú vị và hứng thú, hỉu code hơn. Em debug xog ròi. TKs mọi người. :S
                            UART_BAURATE khoảng bao nhiêu thì đủ à Thầy? Thấp thì thế nào, cao thì thế nào ạ? Em để 115200l.

                            Comment


                            • #59
                              Thấy mọi người build code gặp nhiều vấn đề, nên tôi cũng thử tạo project theo code hướng dẫn trên thread và buid thử, để xem có sai sót gì không:

                              Chỉ có 1 lỗi là thiếu khai báo baudrate mà bạn hieppro89 đã chỉ ra. Các bạn thêm khai báo này vào file "ntAVRnet.h" nhé, file này chúng ta sẽ lưu mọi thông tin cấu hình chung, để sau này có thể sửa đổi dễ dàng.
                              Baudrate tùy mọi người quyết dịch thôi, thấp thì ít sai bit hơn (hiện ra chữ Ai Cập ), nhưng thực ra nếu mạch làm chuẩn và tốc độ chip set đúng thì ít khi sai bit lắm.
                              Nạp thử vào chip bằng mạch nạp tự chế:

                              Thử gắn cáp mạng vào và ping tới mạch:

                              Vậy là OK nhé, code không có sai sót. Tới đây thì chỉ có vậy thôi vì chúng ta mới viết tới giao thức ICMP, để trả lời cho lệnh ping.
                              Các thứ mắm muối gia vị như LCD, ADC,... mọi người tự mình thêm vào nhé.
                              Đang suy nghĩ xem có nên post toàn bộ project vừa build lên không, nhưng kết luận là không. Vì thread này lập ra nhằm giúp mọi người tự mình viết code, hay ít nhất cũng hiểu được code và modify cho phù hợp với mục đích của mình, tự xây dựng project của mình, không khuyến khích "download and build"
                              Mọi người thông cảm nhé, vì máu giáo viên mà . Với lại tôi từng gặp rất nhiều bạn download mạch và source code trên mạng về làm, không hiểu tí gì về mạch cũng như source, nhưng cứ bảo là mình làm được.
                              Nếu ai thực sự gặp khó khăn và không thể tự build code được, cứ liên hệ trực tiếp, tôi sẵng sàng giúp.
                              Còn 4 giao thức nữa: TCP, UDP, HTTP, và DHCP là ta có thể hoàn thành project này. Dạo này công việc ngập đầu, chưa có thời gian viết tiếp tut, mọi người thông cảm nhé. Vì phải giải thích code và giao thức nên cũng mất nhiều thời gian.

                              Comment


                              • #60
                                Nguyên văn bởi hieppro89 Xem bài viết
                                em debug ok rồi, mà mô phỏng = proteus,hiển thị lên terminal toàn kí tự Ai Cập thôi, he he
                                À quên khi khai báo define cho baudrate, các bạn phải thêm ký tự l (long) vào cuối nhé:
                                Code:
                                #define UART_BAUDRATE	9600l
                                Để cho trình biên dịch biết đó là giá trị long, vì trong hàm khởi tạo uart, biến tương ứng là biến long.
                                Last edited by nttam79; 09-11-2011, 11:45.

                                Comment

                                Về tác giả

                                Collapse

                                nttam79 Tìm hiểu thêm về nttam79

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X