Thông báo

Collapse
No announcement yet.

AT89C51 bị ma làm. Nhờ các cao thủ cho ý kiến.

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • AT89C51 bị ma làm. Nhờ các cao thủ cho ý kiến.

    Tình hình là mình lâu lâu quay về 89 làm cái đồng hồ số DS1307 cho thằng em. Code ngon nghẻ, mô phỏng rầm rầm và bắt đầu đi thực hiện. Thực hiện nạp code xong thì chương trình chạy sai, không hiển thị được gì sất. Kiểm tra lại chương trình, mạch in xem có sai đâu ko nhưng không phát hiện lỗi sai ( mô phỏng vẫn chạy kia mà - mình tự code ). Bắt đầu cắt từng đoạn code đi bug và dừng lại nghi ngờ ở việc truy xuất mảng.
    Chương trình thì không có yêu cầu gì quá đáng. Nó đây ạ :
    Code:
    #include <REGX51.h>
    #include "DELAY.c"
    
    unsigned char time_dis[6]	={0,0,0,0,0,0};
    unsigned char disp_i=0;
    
    
    code unsigned char led_hex[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0xFF,0x6F};
    
    
    void main()
    {
    
    	while(1)
    	{
    		P0=0xFF;
    		P2=led_hex[time_dis[0]];
    		P0=0xFE;
    		delay_ms(5);
    	}
    }
    File Delay.c
    Code:
    void delay_ms(unsigned int xTime);
    
    void delay_ms(unsigned int xTime)
    {
    	while(xTime>0)
    	{
    		unsigned int time_temp = 123;
    		while(time_temp>0)
    		{
    			time_temp--;
    		}
    		xTime--;
    	}
    }
    Dịch không báo lỗi, không warning. Mô phỏng không báo lỗi gì nhưng thực tế mạch chạy tầm vài s thì dừng. Reset cũng không chạy lại. Chỉ chạy lại khi ngắt nguồn hoặc gỡ chip ra lắp lại thì chạy tầm vài s tiếp. Có một điều khó hiểu là trên P2, khi treo thì chạm vào Pin nào trên P2 thì Pin đó đổi trạng thái ( vẫn không reset được). Theo các cao nhân thì hiện tượng đó giải thích thế nào ạ
    Pin 31 đã nối Vcc, Chân 9 vẫn có mức 0-1 khi nhấn reset, các biến đã được gán giá trị khi khai báo nên không thể nhận giá trị vớ vẩn khi reset được ?

    Có khi nào mấy con 89 bị ma làm ( mình nạp vào 3 con 89 mới đều như nhau ) ? @@
    Last edited by duong_act; 15-05-2013, 02:01.

  • #2
    Theo tui thấy thì phần truy xuất mảng này có gì sai đâu? chắc time_dis[6] thì có 2 phần tử giành cho giờ 2 phần tử giành cho phút 2 phần tử còn lại có thể là giây hoặc nhiệt độ. Trong quá trình chương trình chạy sẽ update time_dis[] giả như time_dis[]={0,1,4,0,3,0}; khi đem hiển thị sẽ là 01:40:30 ??? Tại tui chưa làm cái này bao giờ nên chỉ đoán được là vậy thôi. Còn khoản quét led thì hình như là bác chả quét gì cả thì phải. Theo tui nghĩ ít nhất phải có 1 cái vòng for theo kiểu:
    Code:
    // Giả sử P0 là  chân select để chọn LED cần hiển thị
    // P0.0 -> Giờ 1
    // P0.1 -> Giờ 2
    // P0.2 -> Phút 1
    // P0.3 -> Phút 2
    // P0.4 -> Giây 1 // Cứ gọi là giây cho dân dã nhé, nếu bác dùng để hiển thị nhiệt độ thì kệ bác
    // P0.5 -> Giây 2
    char x=1;
    P0=0;
    for(i=0;i<6;i++){
         P2=led_hex[time_dis[i]];
         x<<=i;//Trước đó viết nhầm  x>>=i;
         P0=x;
         delay(time);
    }
    Cái này chắc có 1 chuơng trình ngắt thời gian để update thời gian từ RTC sang time_dis hả bác?
    Last edited by myth-coder; 15-05-2013, 15:35. Lý do: Trước đó viết nhầm x>>=i;

    Comment


    • #3
      bạn có gắn con cap 104 giữa chân vcc & gnd của con RTC (ds1307) ? nhớ gắn vào.....
      Mãi đi tìm vàng.

      Comment


      • #4
        Mình dùng Timer để quét nhưng không quét được do truy xuất mảng bị lỗi. Mình treo trở P0 thì ổn rồi
        Cái lạ là truy xuất mình xuất trên P2 cơ mà, không treo trở P0 thì giá trị trên P2 sai ( thiếu nét - không biết do truy xuất sai hay cái gì ?).
        Một điều nữa là tại sao chạm vào P2 thì thay đổi được logic trên chân của P2 ? Rõ ràng giá trị trên P2 là xuất từ trong chip ra cơ mà và trên P2 là IO thông thường ?

        Comment


        • #5
          Hay bác đóng gói cốt quăng nó lên đây coi nào. Chứ mù mờ thế này thì chả biết đường nào mà lần cả.

          Comment


          • #6
            Mình up hết trên rồi kìa. Chỉ với chương trình thế kia thôi đã dính rồi.

            Comment


            • #7
              cho 5 chăm đồng cờ-líp đi ^^

              Comment


              • #8
                bác xóa bit ch chưa

                Comment


                • #9
                  Nguyên văn bởi hungtrinh36 Xem bài viết
                  bác xóa bit ch chưa
                  chỉ mới debug chương trình quét led thôi chưa có đả động gì tới RTC hết mà

                  Comment


                  • #10
                    Bác thử thay delay bằng hàm sau coi sao
                    Code:
                    void sleepi(unsigned n)
                    {
                    	unsigned c=0,z=~0-1000;//1ms
                    	TR1 = 0;           /* Stop Timer 1 */
                    	
                    	TMOD &= ~0x0F;     /* 16-bit, no prescale mode */
                    	TMOD |=  0x10;
                    	
                    	PT1 = 1;           /* High Priority Interrupt */
                    	ET1 = 1;           /* Enable Timer1 Interrupt */
                    	
                    	TR1 = 1;           /* Start Timer 1 */
                    	EA = 1;            /* Enable Global Interrupts */
                    	while(1)
                    	{
                    		TH1=((z>>8)&0xff);//High
                    		TL1=(z&0xff);//Low
                    		if(c>=n)
                    		{
                    			TR1=0;
                    			TF1=0;
                    			return; // Return caller
                    		}
                    		c+=1;
                    		PCON=0x1;// Go idle mode for power saver
                    	}
                    }

                    Comment


                    • #11
                      Nguyên văn bởi chung1608 Xem bài viết
                      cho 5 chăm đồng cờ-líp đi ^^
                      500 đồng ít quá không bán ạ
                      Vấn đề đã được giải quyết. Nguyên nhân do không treo trở trên P0 . Code không có vấn đề gì.
                      Vấn đề là giải phẫu tại sao P0 không gắn trở thì dữ liệu trên P2 sai ( led hiển thị thiếu nét - nét bị thiếu là ngẫu nhiên ). P0 mình dùng điều khiển Anot chung nhưng dùng PNP mà, đâu nhất thiết phải có trở treo ?

                      Comment


                      • #12
                        Nguyên văn bởi duong_act Xem bài viết
                        500 đồng ít quá không bán ạ
                        Vấn đề đã được giải quyết. Nguyên nhân do không treo trở trên P0 . Code không có vấn đề gì.
                        Vấn đề là giải phẫu tại sao P0 không gắn trở thì dữ liệu trên P2 sai ( led hiển thị thiếu nét - nét bị thiếu là ngẫu nhiên ). P0 mình dùng điều khiển Anot chung nhưng dùng PNP mà, đâu nhất thiết phải có trở treo ?
                        do ko có trở treo thì PNP nó bị lơ lửng dẫn tới nhiễu ấy mà ^^

                        Comment


                        • #13
                          Nguyên văn bởi myth-coder Xem bài viết
                          Bác thử thay delay bằng hàm sau coi sao
                          Code:
                          void sleepi(unsigned n)
                          {
                          	unsigned c=0,z=~0-1000;//1ms
                          	TR1 = 0;           /* Stop Timer 1 */
                          	
                          	TMOD &= ~0x0F;     /* 16-bit, no prescale mode */
                          	TMOD |=  0x10;
                          	
                          	PT1 = 1;           /* High Priority Interrupt */
                          	ET1 = 1;           /* Enable Timer1 Interrupt */
                          	
                          	TR1 = 1;           /* Start Timer 1 */
                          	EA = 1;            /* Enable Global Interrupts */
                          	while(1)
                          	{
                          		TH1=((z>>8)&0xff);//High
                          		TL1=(z&0xff);//Low
                          		if(c>=n)
                          		{
                          			TR1=0;
                          			TF1=0;
                          			return; // Return caller
                          		}
                          		c+=1;
                          		PCON=0x1;// Go idle mode for power saver
                          	}
                          }
                          Mình không thích dùng delay bằng Timer. Xét về độ chính xác thì không thể hơn delay bằng vòng lặp. Hiệu quả đem lại của 2 kiểu delay là như nhau trong khi delay bằng timer phức tạp hơn. Nếu tính toán không chính xác thì cho thời gian sai. Với 8051 mình chưa bug delay bằng timer nhưng với PIC ( CCS ) thì khi có ngắt timer, vi điều khiển sẽ thực thi tầm 40 lệnh trước khi chạy hàm ngắt ( 8us ).

                          Comment


                          • #14
                            Thực ra mình không phải dân điện tử và cũng chưa làm thật mấy cái này bao giờ. Chỉ là thấy trên diễn đàn có nhiều người nói rằng 89xxx có hiện tượng bị treo, thì mình nghĩ chắc do nó bị làm việc quá tải. Nên mình mới thiết kế cái hàm hàm delay = timer nhưng cũng không hẳn là timer đâu, đây là 1 chương trình ngắt thời gian nhưng làm nhiệm vụ của hàm delay. Ý định của mình là bình thường khi muốn delay thì mọi người thường tiêu tốn thời gian của CPU 1 cách vô ích, sao không cho nó ngủ, sau đó timer sẽ tự gọi nó dậy sau 1 số khoảng thời gian định sẵn nào đó -> CPU vừa được rảnh 1 khoảng thời gian và chương trình của mình cũng vẫn được làm chậm như ý muốn, nếu vậy thì sẽ tránh hiện tượng CPU bị treo. Hàm delay ở trên mình đưa lên còn thiếu mất mấy dòng như sau:
                            Code:
                            void timer_ISR (void) interrupt 3
                            {
                            	//Do nothing - use for weakup from idle mode
                            }
                            Và đầy đủ của hàm delay sẽ như sau:
                            Code:
                            void sleepi(unsigned n) // Thời gian tính bằng mini giây
                            {
                            	unsigned c=0;//,z=~0-1000;//=64536 //1m
                            	TR1 = 0;           /* Stop Timer 1 */
                            	
                            	TMOD &= ~0x0F;     /* 16-bit, no prescale mode */
                            	TMOD |=  0x10;
                            	
                            	PT1 = 1;           /* High Priority Interrupt */
                            	ET1 = 1;           /* Enable Timer1 Interrupt */
                            	
                            	TR1 = 1;           /* Start Timer 1 */ 
                            	EA = 1;            /* Enable Global Interrupts */
                            	while(1)
                            	{
                            		TH1=0xFC;//((z>>8)&0xff);//High
                            		TL1=0x18;//(z&0xff);//Low
                            		if(c>=n)// Nếu thời gian chờ đã bằng hoặc nhiều hơn thời gian yêu cầu
                            		{
                            			TR1=0;// Tắt timer 1
                            			//TF1=0; //  Xóa cờ tràn <- cái này thực ra cũng không cần thiết 
                            			return; // trở về với chương trình cha
                            		}
                            		// Nếu không muốn dùng thêm biến phụ c thì có thể dùng ngay biến n (n-=1) thì điều kiện sẽ là n<1
                            		c+=1;
                            		PCON=0x1;// Đưa CPU vào chế độ idle (Đưa CPU về chế độ ngủ giữ nguyên nội dung của ram và counter vẫn hoạt động)
                            	}
                            }
                            void timer_ISR (void) interrupt 3
                            {
                            	//Dùng để gọi CPU dậy sau một khoảng thời gian, như setup ở trên thì cứ sau 1ms
                            	//thì hàm này được thực thi, sau khi hàm này kết thúc thì lại chuyển quyền thực thi về cho chương trình chính trước đó
                            	//trong trường hợp này là cuối vòng while ngay sau đoạn PCON=1 (_IDL=1)và lại được trở lại đầu vòng while và thực hiện lại 1 vòng
                            	//Bao gồm nạp lại giá trị cho timer, kiểm tra xem đã đủ thời gian yêu cầu chưa, nếu chưa đủ thì cpu lại tiếp tục đi vào chế độ ngủ.
                            }
                            Tuy thời gian có thể không chính xác tuyệt đối được nhưng CPU được nghỉ trong mỗi khoảng thời gian 1ms, không phải làm việc vô ích (donothing)

                            Comment


                            • #15
                              lâu lâu thấy bạn duong act múa vài đường kiếm cũng bén nhẩy?
                              không thể làm những gì bạn muốn,hãy làm những gì bạn có thể làm .Đời không như mơ

                              Comment

                              Về tác giả

                              Collapse

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

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

                              Collapse

                              Đang tải...
                              X