Thông báo

Collapse
No announcement yet.

Keil C & 8051 [tut]

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

  • #16
    Code:
    #include <regx51.h>
    #define uchar unsigned char
    #define pLed0 P3_2
    #define pLed1 P3_3
    #define pLed2 P3_4
    #define pLed3 P3_5
    #define DataLed P2
    #define SCL P1_0
    #define SDA P1_1
    #define DSW 0xd0
    #define DSR 0xd1
    //giao thuc i2c da san sang
    //================================================
    //cac bien toan cuc
    uchar uLed;//chu y la co 4 led thoi
    uchar gio,phut,giay,tg;//se duoc cap nhat tai moi khi ham ngat duoc goi
    uchar maled[10]={0x21,0x7d,0x13,0x15,0x4d,0x85,0x81,0x3d,0x1,0x5};
    
    //================================================
    void init(void);
    void T0_ISR(void);
    void delay(void);
    void i2cstart(void);
    void i2cstop(void);
    uchar i2cwrite(uchar c);
    uchar i2cread(void);
    uchar i2creadlast(void);
    void scl1(void);
    void capnhatgio(void);
    void khoitaods(void);//kiem tra xem con ds da duoc chay chua
    //neu chua chay thi cho no chay
    //==================================================
    void main(void)
    {
    	init();
    	while(1)
    	{
    	}
    }
    void init(void)
    {
    	//khoi tao timer 0 che do tu dong nap lai
    	//cho phep ngat luon
    	//uchar c;
    	SDA=SCL=1;
    	//bat dau kiem tra con ds
    	khoitaods();
    	TMOD=1;
    	//che do 1 cua bo dinh thoi 0
    	//cho phep ngat thoi gian
    	EA=1;//cho phep ngat
    	ET0=1;//cho phep ngat thoi gian 0
    	//khoi tao cho t0
    	TH0=0xd8;
    	TL0=0xf0;//10.000 us
    	uLed=0;
    	TR0=1;
    	//them phan khoi tao cho 1307 
    
    }
    void T0_ISR(void) interrupt 1
    {
    	//dau tien la dung bo dinh thoi cai da
    	TR0=0;
    	//thuc hien quet led cai da
    	//kiem tra xem led nao can phuc vu
    	//cap nhat lai gio, phut, giay
    	//?????????????????????????????????????????
    	//?????????????????????????????????????????
    	capnhatgio();
    	pLed0=pLed1=pLed2=pLed3=0;
    	switch(uLed)
    	{
    		case 0:
    			pLed0=1;
    			//tach chu so
    			tg=gio>>4;
    			//tg>>=4;
    			DataLed=maled[tg];
    		break;
    		case 1:
    			pLed1=1;
    			tg=gio&0xf;
    			DataLed=maled[tg];
    		break;
    		case 2:
    			pLed2=1;
    			tg=phut>>4;
    			DataLed=maled[tg];
    		break;
    		case 3:
    			pLed3=1;
    			tg=phut&0xf;
    			DataLed=maled[tg];
    		break;
    	}
    	++uLed;
    	if(uLed==4)
    		uLed=0;
    	TH0=0xd8;
    	TL0=0xf0;//10.000 us
    	TR0=1;		
    }
    void scl1(void)
    {
    	SCL=1;
    	while(!SCL);
    }
    void i2cstop(void)
    {
    	SDA=0;
    	scl1();
    	SDA=1;
    	delay();
    }
    uchar i2cwrite(char c)
    {
    	uchar i,ret;
    	for(i=0;i<8;++i)
    	{
    		//lan luot gui tung bit 1 ra
    		SDA=0;
    		if(c&0x80)
    			SDA=1;
    		c<<=1;
    		scl1();
    		delay();
    		SCL=0;
    		delay();
    	}
    	ret=0;
    	//tao xung ack
    	SDA=1;
    	scl1();
    	delay();
    	if(!SDA)
    		ret=1;
    	SCL=0;
    	delay();
    	return ret;
    }
    uchar i2cread(void)
    {
    	uchar ret,i;
    	for(i=0;i<8;++i)
    	{
    		ret<<=1;
    		scl1();
    		delay();
    		ret|=SDA;
    		SCL=0;
    		delay();
    	}
    	//gui tra lai ack
    	SDA=0;
    	scl1();
    	delay();
    	SCL=0;
    	delay();
    	return ret;
    }
    uchar i2creadlast(void)
    {
    	uchar ret,i;
    	for(i=0;i<8;++i)
    	{
    		ret<<=1;
    		scl1();
    		delay();
    		ret|=SDA;
    		SCL=0;
    		delay();
    	}
    	//gui tra lai not ack
    	SDA=1;
    	scl1();
    	delay();
    	SCL=0;
    	delay();
    	return ret;	
    }
    void i2cstart(void)
    {
    	SDA=1;
    	scl1();
    	SDA=0;
    	delay();
    	SCL=0;
    	delay();	
    }
    void delay(void)
    {
    	uchar i;
    	for(i=0;i<5;++i);
    }
    void khoitaods(void)
    {
    	uchar c;
    	i2cstart();
    	i2cwrite(DSW);
    	i2cwrite(0);//ghi vao dia chi 0
    	i2cstart();
    	i2cwrite(DSR);
    	c=i2creadlast();
    	if(c&0x80)
    	{
    		i2cstart();
    		i2cwrite(DSW);
    		i2cwrite(0);
    		i2cwrite(0);
    	}
    	i2cstop();
    }
    void capnhatgio(void)
    {
    	//cap nhat lai gio phut giay
    	i2cstart();
    	i2cwrite(DSW);
    	i2cwrite(0);
    	i2cstart();
    	i2cwrite(DSR);
    	giay=i2cread();
    	phut=i2cread();
    	gio=i2creadlast();
    	i2cstop();
    }

    Comment


    • #17
      Nguyên văn bởi kidteam Xem bài viết
      Code:
      #include <regx51.h>
      #define uchar unsigned char
      #define pLed0 P3_2
      #define pLed1 P3_3
      #define pLed2 P3_4
      #define pLed3 P3_5
      #define DataLed P2
      #define SCL P1_0
      #define SDA P1_1
      #define DSW 0xd0
      #define DSR 0xd1
      //giao thuc i2c da san sang
      //================================================
      //cac bien toan cuc
      uchar uLed;//chu y la co 4 led thoi
      uchar gio,phut,giay,tg;//se duoc cap nhat tai moi khi ham ngat duoc goi
      uchar maled[10]={0x21,0x7d,0x13,0x15,0x4d,0x85,0x81,0x3d,0x1,0x5};
      
      //================================================
      void init(void);
      void T0_ISR(void);
      void delay(void);
      void i2cstart(void);
      void i2cstop(void);
      uchar i2cwrite(uchar c);
      uchar i2cread(void);
      uchar i2creadlast(void);
      void scl1(void);
      void capnhatgio(void);
      void khoitaods(void);//kiem tra xem con ds da duoc chay chua
      //neu chua chay thi cho no chay
      //==================================================
      void main(void)
      {
      	init();
      	while(1)
      	{
      	}
      }
      void init(void)
      {
      	//khoi tao timer 0 che do tu dong nap lai
      	//cho phep ngat luon
      	//uchar c;
      	SDA=SCL=1;
      	//bat dau kiem tra con ds
      	khoitaods();
      	TMOD=1;
      	//che do 1 cua bo dinh thoi 0
      	//cho phep ngat thoi gian
      	EA=1;//cho phep ngat
      	ET0=1;//cho phep ngat thoi gian 0
      	//khoi tao cho t0
      	TH0=0xd8;
      	TL0=0xf0;//10.000 us
      	uLed=0;
      	TR0=1;
      	//them phan khoi tao cho 1307 
      
      }
      void T0_ISR(void) interrupt 1
      {
      	//dau tien la dung bo dinh thoi cai da
      	TR0=0;
      	//thuc hien quet led cai da
      	//kiem tra xem led nao can phuc vu
      	//cap nhat lai gio, phut, giay
      	//?????????????????????????????????????????
      	//?????????????????????????????????????????
      	capnhatgio();
      	pLed0=pLed1=pLed2=pLed3=0;
      	switch(uLed)
      	{
      		case 0:
      			pLed0=1;
      			//tach chu so
      			tg=gio>>4;
      			//tg>>=4;
      			DataLed=maled[tg];
      		break;
      		case 1:
      			pLed1=1;
      			tg=gio&0xf;
      			DataLed=maled[tg];
      		break;
      		case 2:
      			pLed2=1;
      			tg=phut>>4;
      			DataLed=maled[tg];
      		break;
      		case 3:
      			pLed3=1;
      			tg=phut&0xf;
      			DataLed=maled[tg];
      		break;
      	}
      	++uLed;
      	if(uLed==4)
      		uLed=0;
      	TH0=0xd8;
      	TL0=0xf0;//10.000 us
      	TR0=1;		
      }
      void scl1(void)
      {
      	SCL=1;
      	while(!SCL);
      }
      void i2cstop(void)
      {
      	SDA=0;
      	scl1();
      	SDA=1;
      	delay();
      }
      uchar i2cwrite(char c)
      {
      	uchar i,ret;
      	for(i=0;i<8;++i)
      	{
      		//lan luot gui tung bit 1 ra
      		SDA=0;
      		if(c&0x80)
      			SDA=1;
      		c<<=1;
      		scl1();
      		delay();
      		SCL=0;
      		delay();
      	}
      	ret=0;
      	//tao xung ack
      	SDA=1;
      	scl1();
      	delay();
      	if(!SDA)
      		ret=1;
      	SCL=0;
      	delay();
      	return ret;
      }
      uchar i2cread(void)
      {
      	uchar ret,i;
      	for(i=0;i<8;++i)
      	{
      		ret<<=1;
      		scl1();
      		delay();
      		ret|=SDA;
      		SCL=0;
      		delay();
      	}
      	//gui tra lai ack
      	SDA=0;
      	scl1();
      	delay();
      	SCL=0;
      	delay();
      	return ret;
      }
      uchar i2creadlast(void)
      {
      	uchar ret,i;
      	for(i=0;i<8;++i)
      	{
      		ret<<=1;
      		scl1();
      		delay();
      		ret|=SDA;
      		SCL=0;
      		delay();
      	}
      	//gui tra lai not ack
      	SDA=1;
      	scl1();
      	delay();
      	SCL=0;
      	delay();
      	return ret;	
      }
      void i2cstart(void)
      {
      	SDA=1;
      	scl1();
      	SDA=0;
      	delay();
      	SCL=0;
      	delay();	
      }
      void delay(void)
      {
      	uchar i;
      	for(i=0;i<5;++i);
      }
      void khoitaods(void)
      {
      	uchar c;
      	i2cstart();
      	i2cwrite(DSW);
      	i2cwrite(0);//ghi vao dia chi 0
      	i2cstart();
      	i2cwrite(DSR);
      	c=i2creadlast();
      	if(c&0x80)
      	{
      		i2cstart();
      		i2cwrite(DSW);
      		i2cwrite(0);
      		i2cwrite(0);
      	}
      	i2cstop();
      }
      void capnhatgio(void)
      {
      	//cap nhat lai gio phut giay
      	i2cstart();
      	i2cwrite(DSW);
      	i2cwrite(0);
      	i2cstart();
      	i2cwrite(DSR);
      	giay=i2cread();
      	phut=i2cread();
      	gio=i2creadlast();
      	i2cstop();
      }
      I. Nguyên nhân:

      Trong hàm main, bạn gọi hàm "init". Trong hàm "init" bạn gọi hàm "khoitaods". Trong hàm "khoitaods" bạn có gọi 3 hàm là: "i2cstart", "i2cwrite", "i2creadlast". Như vậy có thể nói là trong hàm main bạn gọi 3 hàm "i2cstart", "i2cwrite", "i2creadlast" gián tiếp qua các hàm "init" và "khoitaods".

      Trong chương trình con phục vụ ngắt bạn cũng có gọi 3 hàm này gián tiếp qua hàm "capnhatgio".

      Vì vậy trong hàm main và chương trình con phục vụ ngắt bạn gọi đồng thời 3 hàm "i2cstart", "i2cwrite", "i2creadlast".

      Chú ý rằng đồng thời là do trình biên dịch hiểu thôi, chứ thật sự nó không thể nào gọi đồng thời đc vì trong hàm main bạn có gọi 3 hàm này chỉ 1 lần duy nhất trước khi cho phép ngắt.

      Cuối cùng trình biên dịch đưa ra 2 cảnh báo cho 2 hàm "i2cwrite" và "i2creadlast". Lẽ ra như phân tích từ đầu tới giờ thì phải là 3 cảnh báo cho cả 3 tên mới đúng chứ, đằng này hàm "i2cstart" lại thoát nạn. Nguyên nhân là cảnh báo multiple call này chỉ áp dụng cho các hàm có sử dụng biến cục bộ bên trong hoặc tham số truyền cho hàm vượt ngoài khả năng truyền tham số bằng các thanh ghi R0÷R7, còn ngược lại thì đều được phép.

      II. Cách khắc phục

      Cách 1:

      Như phía trên mình đã phân tích, các hàm này không thể nào được gọi đồng thời được. Vì vậy các cảnh báo này chẳng ảnh hưởng gì đến hòa bình thế giới cả. Nếu bạn ko cảm thấy phiền vì chúng có thể để nguyên như vậy. Ko thì yêu cầu Keil không cảnh báo cho các lỗi có đánh số là 15 bằng cách mởi hộp thoại Option for Target, chọn tab BL51 Misc, ở textbox có nhãn Disable Warning Numbers bạn gõ vào số 15 -> Ok. Biên dịch lại sẽ được thông báo là 0 Error (s), 0 Warning (s)



      Cách 2:

      Bạn thêm 3 hàm nữa nội dung như 3 hàm trên nhưng tên đặt khác 1 chút. Sau đó bạn sử dụng hai nhóm này, 1 cho main và 1 cho chương trình phục vụ ngắt. Với cách này thì bộ nhớ Code sẽ bị tăng dung lượng lên 1 ít. Nhưng bù lại đảm bảo an toàn trong mọi trường hợp (ngoại trừ hết bộ nhớ Code, he he)

      Cách 3:

      Nếu trong vòng lặp while 1 bạn không xử lý gì nữa, bạn có thể thay đổi code 1 chút xíu như sau:
      Code:
      while(1)
      {
      	PCON |= 0x01;  	// Vi dieu khien vao che do IDLE
      
      	// Chi thuc hien doan lenh nay sau moi lan ngat
      	capnhatgio();
      	pLed0=pLed1=pLed2=pLed3=0;
      	switch(uLed)
      	{
      		case 0:
      			pLed0=1;
      			//tach chu so
      			tg=gio>>4;
      			//tg>>=4;
      			DataLed=maled[tg];
      		break;
      		case 1:
      			pLed1=1;
      			tg=gio&0xf;
      			DataLed=maled[tg];
      		break;
      		case 2:
      			pLed2=1;
      			tg=phut>>4;
      			DataLed=maled[tg];
      		break;
      		case 3:
      			pLed3=1;
      			tg=phut&0xf;
      			DataLed=maled[tg];
      		break;
      	}
      	++uLed;
      	if(uLed==4)
      		uLed=0;
      	TH0=0xd8;
      	TL0=0xf0;//10.000 us
      	TR0=1;	
      }
      Và trong chương trình ngắt chỉ còn lại 1 lệnh duy nhất là TR0 = 0 vơi mục đích là dừng Timer0 lại. Vì vậy sẽ khắc phục được lỗi.

      Một lời khuyên nhỏ dành cho các bạn: khi lập trình bằng C, bạn nên tổ chức chương trình thành các modul riêng, không nên viết tất cả trong 1 file như thế này. Ban đầu bạn sẽ thấy cách viết theo modul khó và phức tạp, nhưng khi quen rùi, nó sẽ giúp bạn quản lý chương trình, tổ chức thư viện tốt hơn. Nếu biết cách lập trình theo modul thì chỉ sau 1÷2 năm làm việc với một dòng vi xử lý nào đó, bạn sẽ có một thư viện hàm phong phú tha hồ sử dụng. Và các bạn có thể dễ dàng chia sẽ thư viện với nhau, làm việc nhóm dễ dàng hơn.
      Last edited by dangemailbox; 14-05-2012, 15:04.

      Comment


      • #18
        Giải trí một xíu nhé.
        Mời các bạn xem hình Graffiti đậm phong cách Nhật Bản + Microcontrollers











        Các bạn có thể vào website sau để tìm thêm nhiều hình ảnh và các bài tut về điện tử: http://elm-chan.org/
        Last edited by dangemailbox; 14-05-2012, 17:50.

        Comment


        • #19
          tiếp tục đăng thêm đi pro dangemailbox ơi. bài của bạn viết hay lắm đấy.

          Comment


          • #20
            Mới làm xong cái đồng hồ P89V51RD2 & Ds1307 các bạn xem thử nha.



            Các Tính năng
            1. Hiển thị ngày giờ.
            2. Cài đặt ngày giờ.
            3. Chọn mode hiển thị 12h/24h.
            4. Điều khiển độ sáng đèn nền LCD.
            5. Hẹn giờ điều khiển 6 relay.
            6. Remote RF điều khiển Relay hoặc gửi mã phím (A,B,C,D) lên máy tính.
            7. Remote RF có thể chọn Relay cần điều khiển cho từng nút (4 nút).
            8. Relay cũng có thể được điều khiển bằng các nút nhấn trên board.
            9. Hiển thị trạng thái của Relay.
            10. Lưu các cài đặt, giờ hẹn, ... trên Ds1307.
            11. Tập lệnh Giao tiếp với máy tính (hiện tại là 15 lệnh).
            Ví dụ:
            Từ PC gửi lệnh ReaD Date, cú pháp như sau:
            RDD=?;
            thì vi điều khiển sẽ gửi lên thứ, ngày, tháng, năm -> 7_26/05/12;

            Hoặc từ máy tính gửi lệnh WRite Time, cú pháp như sau:
            WRT=10:30:00;
            thì vi điều khiển sẽ cập nhật giờ.

            Code khoảng 3000 dòng, viết trong 10 ngày (giờ nhìn lại cũng sợ). Nếu các bạn muốn xem code mình có up lên ở phía dưới (nhưng tốt nhất là đừng xem).

            Trong code có sử dụng enum, union, con trỏ hàm, trạng thái máy, các chỉ thị cho trình biên dịch (#message, #error), các chỉ thị cho linker (overlay). Viết theo kiểu project, có file header (.h), file hàm (.c) như I2C, Ds1307, Delay, ...). Nói chung là rất rắc rối, nhưng đáng để tham khảo, chỉ dành cho các bạn đủ đam mê mới đọc nổi code. Bạn nào đọc không nổi code cũng có thể trích lọc ra phần thư viện để sử dụng lại.

            Chúc các bạn không bị tẩu quỷ nhập ma khi đọc xong code.

            Code đây: http://www.mediafire.com/download.php?re6cmq2dl9u99hl

            Trong file nén có lun 1 file mô phỏng Proteus, nhưng chỉ dùng để xem kết nối phần cứng tương đương với phần cứng thật thôi các bạn nhé.

            Form giao tiếp với máy tính các bạn tự thiết kế nha!! Mình chưa làm xong. Các bạn có thể làm đơn giản như thế này: tạo 1 form có 1 richtextbox để gửi lệnh và nhận trả lời của vi điều khiển (giống như cửa sổ cmd của Windows hoặc command window của matlab ý. He he)
            Last edited by dangemailbox; 26-05-2012, 13:50.

            Comment


            • #21
              khiếp
              quảng cáo ghê
              Code khoảng 3000 dòng, viết trong 10 ngày (giờ nhìn lại cũng sợ). Nếu các bạn muốn xem code mình có up lên ở phía dưới (nhưng tốt nhất là đừng xem).
              Nói chung là rất rắc rối, nhưng đáng để tham khảo, chỉ dành cho các bạn đủ đam mê mới đọc nổi code. Bạn nào đọc không nổi code cũng có thể trích lọc ra phần thư viện để sử dụng lại.

              3000 dòng thì cũng không quá ghê gớm
              dân lập trình nếu ai pro thì đã từng làm việc với mấy MB code ấy chứ
              thế này thì bõ bèn gì

              Comment


              • #22
                Hi, đang mùa thi, chẳng ai nói chuyện cả, buồn quá, lên đây quảng cáo chơi, thông cảm nha!

                Ghi rõ thông tin để bạn nào cần thì down, cũng không có ý gì khác đâu.
                Last edited by dangemailbox; 26-05-2012, 22:49.

                Comment


                • #23
                  không có gì mà
                  nói vậy thôi
                  mấy câu nhưng tốt nhất là đừng xem
                  chỉ dành cho các bạn đủ đam mê mới đọc nổi code

                  chú nên xem lại

                  Comment


                  • #24
                    Hì, mới làm xong (thật ra là gần xong thôi) cái Form giao tiếp, anh em xem thử, đóng góp ý kiến nha.

                    Các chức năng gồm:

                    - Tự động dò cổng COM (9600bps) & Kết nối.
                    - Đọc và ghi trạng thái của các Relay, đổi tên các Relay phù hợp với thiết bị kết nối với Relay.
                    - Đồng bộ ngày giờ với máy tính.
                    - Điều khiển phần mềm trên máy tính (Windows Media Player, KMPlayer, Powerpoint) bằng cách gửi phím tắt (Sendkey)
                    - Giao diện đồ hoạ và giao diện dòng lệnh (2 lệnh như cls - xoá màn hình và exit thì sẽ thực hiện trên máy tính, các lệnh khác gửi xuống vi điều khiển và nhận kết quả trả lời của vi diều khiển).



                    Viết trên Visual Studio 2008 - Ngôn ngữ C#
                    Source code: CSharp_Form
                    Last edited by dangemailbox; 02-06-2012, 16:57.

                    Comment


                    • #25
                      Hic video mờ quá, up mấy cái hình lên.

                      Tab GUI


                      Tab CMD


                      Tab Remote Control


                      Tab About


                      Còn Tab Setting chưa làm xong.

                      Comment


                      • #26
                        các bác nên tập trung vào việc hướng dẫn giải đáp thắc mắc cho các mem thì hay hơn! ^^

                        Comment


                        • #27
                          Nguyên văn bởi dangemailbox Xem bài viết
                          Hic video mờ quá, up mấy cái hình lên.

                          Tab GUI


                          Tab CMD


                          Tab Remote Control


                          Tab About


                          Còn Tab Setting chưa làm xong.
                          Cho em hỏi hơi ngu tí nhé !
                          Thật ra cái phần mềm này của bác nó có tác dụng gì, nó hỗ trợ được gì trong việc lập trình VĐK?

                          Comment


                          • #28
                            Cái này là phần mềm giao tiếp với board (đồng hồ P89V51RD2 & Ds1307) mà mình up lên ở trang 2 đó. Hôm trước mình mới viết xong cho vi điều khiển, đến hôm nay mới viết phần mềm cho máy tính giao tiếp điều khiển board.

                            Comment


                            • #29
                              Viết tiếp hướng dẫn sử dụng Keil C đi bạn, mình cũng mới học cái này và cũng còn mơ mơ hồ hồ lắm, mình thấy bạn viết rất hay đó cố gắng phát huy tiếp nhé.

                              Comment

                              Về tác giả

                              Collapse

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

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

                              Collapse

                              Đang tải...
                              X