Thông báo

Collapse
No announcement yet.

tutorial cho HTPIC

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

  • #76
    Nguyên văn bởi ngohaibac Xem bài viết
    Tiếp theo là về module I2C, một chuẩn giao tiếp quan trọng khi giao tiếp với ngoại vi như EEPROM, RTS(DS1307),...

    Do đó, mình xin cung cấp cho các bạn các hàm và thực thi của các hàm này trên HTPIC. Mình có tham khảo cả ở bọn htsoft nhưng nó viết sai một số hàm không chạy được, mình đã viết lại toàn bộ.

    Đầu tiên là hàm I2C.h:

    Code:
    //I2C.h
    //Declare some functions
    void I2C_Init(void);          // khởi tạo I2C ở chế độ Master, Baud = 100 Khz
    void I2C_waitForIdle(void); // Chờ khi nào đường bus ở chế độ Idle (rảnh rỗi)
    void I2C_Start(void);        // Khởi động I2C - Master chiếm đường bus
    void I2C_repStart(void);   // Chế độ Restart
    void I2C_stop(void);         // Stop I2C - Master nhường đường bus cho thiết bị khác
    unsigned char I2C_write( unsigned char I2CWriteData ); // ghi một byte lên đường SDA
    unsigned char I2C_read( unsigned char ack ); // Đọc một byte với mã ACK (ACK = 0 nếu ack = 1, và ACK = 1 nếu ack = 0) -> dùng xác nhận từ master đối với slave.
    void I2C_NACK(void);  // tạo bít Not Ack
    Và sau đây là thực thi của các hàm này:

    Code:
    // I2C.c
    # include "pic.h"
    # include "I2C.h"
    //======================================================================================================
    void I2C_Init(void){
    /*	// Configure for Master Mode
    	SSPM3 = 1;
    	SSPM2 = 0;
    	SSPM1 = 0;
    	SSPM0 = 0;				ss	// I2C Master Mode, clock = Fosc/(4*(SSPADD + 1));
    	
    	WCOL = 0;					//No conllision
    	
    	SSPEN = 1;					// Enables the serial port and 
    */	
    	SSPCON = 0b00101000;		// set IIC port to Master mode with BRG	
    	SSPSTAT = 0b00000000;		// Standard speed mode - 100Hz
    	SSPCON2 = 0;
    	
    	//TRIS_SCL = 0;
    	//TRIS_SDA = 0;				// configure SDA and SCL as Output
    	
    	SSPADD = 9;			   	 // BAUD = 100KHz
    	SSPIF = 0;      				// clear SSPIF interrupt flag
     	BCLIF = 0;      				// clear bus collision flag
    	STAT_CKE  = 0;     			// use I2C levels      worked also with '0'
     	STAT_SMP = 1;     			// disable slew rate control  worked also with '0'
    }
    //=============================================================================
    void I2C_waitForIdle(void)
    {
     	while (( SSPCON2 & 0x1F ) | STAT_RW) ; //CLRWDT(); // wait for idle and not writing
    }
    
    //=============================================================================
    void I2C_Start(void){
    	//SSPIF = 0;
    	SEN = 1;
    	//while(!SSPIF);
    	while(SEN);
    }
    //==============================================================================
    void I2C_repStart(void)
    {
    	 I2C_waitForIdle();
    	 RSEN = 1;
    }
    //=============================================================================
    void I2C_stop(void)	
    {
    	 I2C_waitForIdle();
    	 PEN = 1; 
    }
    //==============================================================================
    unsigned char I2C_write( unsigned char I2CWriteData ){
    	 I2C_waitForIdle();
    	 SSPBUF = I2CWriteData;
    	 I2C_waitForIdle();
    	  return (!ACKSTAT); // function returns '1' if transmission is acknowledged	
    	// 1: Success
    	// 0: Fail to send 
    }
    //============================================================================
    unsigned char I2C_read( unsigned char ack ){
    	unsigned char I2C_ReadData;
    	 I2C_waitForIdle();
    	 RCEN = 1;
    	 I2C_waitForIdle();
    	 I2C_ReadData = SSPBUF;
    	 I2C_waitForIdle();
    	 if ( ack )  	ACKDT=0;
        	 else             ACKDT = 1;
     	 ACKEN = 1;               // send acknowledge sequence
    	 I2C_waitForIdle();
    	 return( I2C_ReadData );
    }
    /******************************************************************************************/
    
    void I2C_NACK(void)
    {
    	I2C_waitForIdle();
    	if (ACKSTAT){
    		PEN=1;						//Stop
       		I2C_waitForIdle();			//Wait until action is finished
    		while(PEN);
       	};
    }
    Còn việc dùng nó quá đơn giản, ví dụ với Ds1307 thì đầu tiên bạn phải:

    - Khởi tạo I2C bằng I2C_Start();
    - Start bằng I2C_Start();
    - Chọn slave giao tiếp bằng cách ghi địa chỉ và bit RW tương ứng với chế độ đọc hay ghi.
    - Ghi dữ liệu lựa chọn byte nào cần ghi hay cần đọc trong bảng RAM của DS1307.
    - Ghi dữ liệu hay là đọc dữ liệu.

    Chú ý: khi ghi xong, muốn đọc thì phải làm lại tức là phải restart nhé.

    Chúc các bạn thành công.

    anh Bắc kaka ơi sao em viết như anh hướng dẫn rồi kiểm tra nó lại báo lỗi
    " I2C.h " vậy? anh hướng dẫn cụ thể hơn đi nếu anh có thể gửi cho em 1 bài hoàn chỉnh thì càng tốt (anh gửi vào gmail cho em nhé em cảm ơn anh manhdt87@gmail.com )vì em lần đầu làm i2c nên ko hiểu lắm mong anh thông cảm, em thấy thiên hạ làm nhiều rồi mà em chưa làm được cũng thấy mình kém quá mong anh giúp đỡ!!!!

    Comment


    • #77
      Các cao thủ xem giúp mình thư viện LCD này, mình mới học HT nên còn gà quá

      Code:
      /*
       *    Thu vien LCD 
       
      
       *    PORTB bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
       *    PORTB bit 4 is connected to the LCD RS input (register select)
       *    PORTA bit 5 is connected to the LCD EN bit (enable)
          
       */
      
      #include    <htc.h>
      #include    "lcd.h"
      
      #define    LCD_RS RB4
      
      #define LCD_EN RB5
      
      #define LCD_DATA    PORTB
      
      #define    LCD_STROBE()    ((LCD_EN = 1),delay_us(2);(LCD_EN=0))
      
      
      //==========================================================================================
      void delay_us (unsigned char us){
          while(us--){
              asm("nop");
              asm("nop");
              };
      }
      
      //=======================================================
      //==========================================================================================
      void delay_ms(unsigned char  ms){
          unsigned char    i, j;
          while(ms--){
              for (i = 0; i < 20; i++)
                  for (j = 0; j < 100; j++)
                      asm("nop");
              };
      }
      // ==============================================================
      
      unsigned char LCD_getByte (void){
          unsigned char retval;                                     // Return value
          LCD_TRIS_PORT = 0xFF;                                // Set port to all input
          LCD_RW = 1;                                            // Tell LCD we want to read
          delay_us(2);
          LCD_E = 1;                                                // Do the read
          delay_us(2);
          retval = LCD_DATA_PORT;
          LCD_E = 0;
          LCD_TRIS_PORT = 0x00;                                // Set port back to outputs
          return (retval);
      }
      //===========================================================
      /* write a byte to the LCD in 4 bit mode */
      void
      lcd_write(unsigned char c)
      {
          
          delay_us(40);
          LCD_DATA = ( ( c >> 4 )& 0xFF);
          LCD_STROBE();
          LCD_DATA = ( c & 0xFF);
          LCD_STROBE();
      
      }
      
      /*
       *     Clear and home the LCD
       */
      
      void
      lcd_clear(void)
      {
          LCD_RS = 0;
          lcd_write(0x1);
          delay_ms(2);
      }
      
      /* write a string of chars to the LCD */
      
      void
      lcd_puts(const char * s)
      {
      
          LCD_RS = 1;    // write characters
          while(*s)
              {
              lcd_write(*s++);
              delay_ms(20);
              }
          
      }
      
      /* write one character to the LCD */
      
      void
      lcd_putch(char c)
      {
          
          LCD_RS = 1;    // write characters
          lcd_write( c );
          
      }
      
      
      /*
       * Go to the specified position
       */
      
      void
      lcd_goto(unsigned char pos)
      {
          LCD_RS = 0;
          lcd_write(0x80+pos);
      }
          
      /* initialise the LCD - put into 4 bit mode */
      void
      lcd_init()
      {
          char init_value;
      
      //    ADCON1 = 0x06;    // Disable analog pins on PORTA
      
          init_value = 0x38;
          TRISB=0;
      
          LCD_RS = 0;
          LCD_EN = 0;
      
          
          delay_ms(15);    // wait 15mSec after power applied,
          LCD_DATA     = init_value;
          LCD_STROBE();
          delay_ms(5);
          LCD_STROBE();
          delay_us(200);
          LCD_STROBE();
          delay_us(200);
          LCD_DATA = 0x12;    // Four bit mode
          LCD_STROBE();
      
          lcd_write(0x28); // Set interface length
          lcd_write(0xF); // Display On, Cursor On, Cursor Blink
          lcd_clear();    // Clear screen
          lcd_write(0x6); // Set entry Mode
      }
      Last edited by namqn; 28-02-2009, 17:11. Lý do: định dạng code

      Email:
      Website:
      Handphone:

      Comment


      • #78
        Nguyên văn bởi ngohaibac Xem bài viết
        Có lẽ bài toán nháy led là bài toán đơn giản và tạo hứng thú cho các bạn học vi điều khiển. Tôi xin mạn phép up chương trình nháy led đơn giản và xin các bạn cho ý kiến là liệu có thể tối ưu chương trình này đến mức nào nữa?


        Miêu tả phần cứng: nối các chân của PORTD với các 8led. Các chân còn lại của led nối với một con trở hạn dòng 330Ohm, sau đó nối với GND.

        Đây là sơ đồ nguyên lý:


        Phần mềm: dùng HTPIC.

        Hiện tuợng: các bạn chạy thử xem thế nào

        Giải pháp: có 2 giải pháp là dùng ngắt hoặc dùng delay.

        Chương trình đầu là dùng delay:

        Sau đây là chương trình:

        Code:
        #include<pic.h>
        __CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
        //================================================================
        //==  ham Delay doi so la so miligiay can gay tre
        void delayMS(unsigned int time){
        	while(time--){
        		TMR0 = 6;
        		T0IF = 0; // xoa co ngat 
        		while(!T0IF);
        	};
        }
        
        // == Ham khoi tao cho chip PIC16F877A
        void init(void){
        	// Khoi tao I/O cho cac port
        	ADCON1 = 0x07;  // PortA dung la I/O Port
        	TRISA = 0xFF; // Port A as input
        	TRISB = 0xFF;
        	TRISC = 0xFF;
        	TRISD = 0x00;// PortD as output
        	
        	// Khoi tao cho cac thanh ghi	
        	OPTION  = 0x00; // dung prescaler cho timer0 voi ti le la 1:2
        }
        
        // Chuong trinh chinh
        void main(void){
        	unsigned char i;
        	 init();
        	while(1){
        		for(i = 0;i<8;i++){
        			 PORTD = (1<<i) + (1<<(7-i));
        			delayMS(5000);
        		};
        	};	
        }
        Câu lênh PORTD = (1<<i) + (1<<(7-i)); là dùng toán tử dịch bít.

        File gửi kèm có 2 file: PJ1.c và PJ2.c . PJ1.C là chương trình dùng delay, PJ2 là dùng ngắt.

        Xin mọi người cho ý kiến.
        Anh có thể hướng dẫn cụ thể công thức tính thời gian cho tròn 1 giây được không ah.Em đã thử giả sử Thạch anh dùng ngoài của anh là 8Mhz,20Mhz nhưng không sao tinh ra được 1s giống ý của anh.
        void delayMS(unsigned int time){
        while(time--){
        TMR0 = 6;
        T0IF = 0; // xoa co ngat
        while(!T0IF);
        };
        phần mềm c.r.a.c.k hoặc không dùng máy tính nữa !

        Comment


        • #79
          em cũng có câu hỏi giống bạn này . mong các anh chỉ thêm về cách tính toán khi dùng delay
          |

          Comment


          • #80
            Ngat timer1 khong hoat dong

            xin chào các anh em mới tìm hiểu về PIC vào HT Pic. Em có viết thử một số chuơng trình nhưng khong chạy các anh chị chỉ giúp coi viết lỗi cho nào với:
            Code:
            #include "pic.h"
            #include "htc.h"
            //#include "pic16f887.h"
            #include "delay.h"
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            __CONFIG(0x2cf2);
            __CONFIG(0x0700);
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            unsigned char reload,reload1;
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            void init();
            void init_timer0();
            void init_timer1();
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            void main()
            {
            	init();
            	init_timer0();
            	init_timer1();
            
            	while(1)
            	{
            		//PORTA=0;
            		//DelayMs(100);
            		//PORTA=0xff;
            		//DelayMs(100);
            		RA0=TMR1IF;
            	}
            }
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            void init()
            {
            	TRISD=0;
            	PORTD=0;
            	TRISA=0;
            	PORTA=0;
            	TRISC=0;
            	PORTC=0;
            	TRISB=0x00;
            	PORTB=0x00;	
            
            }
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            void init_timer0()
            {
            	OPTION_REG=0b0100;
            	//T0CS=0;
            	T0IE=1;
            	GIE=1;
            
            }
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            void init_timer1()
            {
            	T1CKPS0=1; 
            	T1CKPS1=0;
            	TMR1CS=0;	
            
            	T1SYNC=0;
            	TMR1GE=0;
            	TMR1ON=1;
            
            	TMR1IE=1;
            	GIE=1;
            
            }
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            static void interrupt 
            timer_isr(void)
            {
            	if(T0IF&T0IE)
            	{
            	T0IF = 0;
            	T0IE=0;
            	if(reload == 0)
            		{
            			reload=50;
            			PORTD++;	// effect a change on PORTB
            		}
            		TMR0=0;
            		reload--;
            	T0IE=1;
            	}
            	if(TMR1IF&TMR1IE)
            	{	
            		TMR1IE=0;
            		TMR1IF = 0;
            		TMR1IE=1;
            		PORTC++;
            		reload1--;
            		if(reload1 == 0)
            		{
            			reload1=10;
            			PORTB++;	// effect a change on PORTB
            		}
            		TMR1IE=1;
            	}
            }
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            Theo nhi em test thì hình như ngắt timer1 khong hoat đong. KHi khong cho phép ngat Timer 0 là chuong trình ngat timer1 đứng luôn. Các anh chị chỉ giúp em sai chỗ nào?
            cảm ơn các anh chị rat nhiều

            Comment


            • #81
              Ngat capture khong hoat dong???

              mình đã tìm ra nguyên nhân làm cho ngắt timer 1 không hoạt động là do trong khởi tạo ngat mình khong set bit PEIE=1 như vậy doan code khoi tạo timer1 phải thêm như sau
              Code:
              void init_timer1()
              {
              	TMR1CS=0;
              	T1CKPS0=1;
              	T1CKPS1=1;
              	T1SYNC=1;
              	TMR1GE=0;
              	TMR1ON=1;
              	TMR1IE=1;
              	PEIE=1;
              	ei();
              }
              nhưng sau khi giải quyết được thằng timer1 lại vấp quả bí khác đó là ngắt capture không hoat động. Trong phần này không thấy các anh chị nói đến phần này. Rất mong các anh chị chia sẻ. Em thấy phần này ứng dụng cho tính toán tốc độ do encoder trả về rất nhiều. Dưới đây là doạn code em viết nhưng chưa chạy anh chị nào biết bí chỗ nào chỉ em với>
              Code:
              #include "pic.h"
              
              __CONFIG(0x2fc2);
              __CONFIG(0x700);
              
              unsigned long	NumOver,EndTime,StartTime,PulseTicks;
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void init();
              void init_timer1();
              void init_capture();
              void init_timer0();
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void main()
              {
              	init();
              //	init_timer0();
              	init_capture();
              	while(1)
              	{
              		//PORTB=TMR1H;
              	}
              }
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void init()
              {
              	ADCON0 = 0; //shut off ADC module
              	ANSEL = 0x00; //all PINs are digital IO
              	ANSELH = 0x00;	
              	OPTION_REG = 0x07;
              	TRISB=0x00;
              	PORTB=0;
              	TRISA=0x00;
              	PORTA=0;
              	TRISD=0x00;
              	PORTD=0;
              }
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void init_timer0()
              {
              	OPTION_REG=0x0111;
              	T0IF=0;
              	T0IE=1;
              	PEIE=1;
              	ei();
              }
              void init_timer1()
              {
              	TMR1CS=0;
              	T1CKPS0=1;
              	T1CKPS1=1;
              	T1SYNC=1;
              	TMR1GE=0;
              	TMR1ON=1;
              	TMR1IE=1;
              	PEIE=1;
              	ei();
              }
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void init_capture()
              {
              	init_timer1();
              	CCP1CON=0x100;
              	CCP1IE=1;
              	PEIE=1;
              	ei();
              	TRISC2=0;
              }
              //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              void interrupt IntVecter(void)
              {
              	if(T0IF&T0IE)
              	{
              		T0IF=0;
              		PORTA++;
              	}
              	if(TMR1IF&TMR1IE)
              	{
              		++NumOver;
              		PORTB++;
              	}
              	if(CCP1IF&CCP1IE)
              	{
              		CCP1IF=0;
              		EndTime=(0x100*CCPR1H)+CCPR1L;
              		PulseTicks=(NumOver*0x10000)-StartTime+EndTime;
              		StartTime=EndTime;
              		NumOver=0;
              		PORTD++;
              	}
              }
              Hien tuong ban dau nhận định là không thể ngắt capture.????:

              Comment


              • #82
                cảm ơn anh ngohaibac rất nhiều!

                Comment


                • #83
                  A Bắc ơi, sao e vẽ mô phỏng trên Protues như mạch của a, chạy file đấy luôn,nhưng sao nó không chạy được ạ.
                  A có thể cho e xin nguyên nhân nó có thể là do vấn đề gì được không ạ??
                  E cảm ơn!

                  Kích từ, điều tốc, nhiệt độ , mức dầu, bảo vệ, đo mực nước, thông báo lũ...cho nhà máy Thủy Điện.

                  Comment

                  Về tác giả

                  Collapse

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

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

                  Collapse

                  Đang tải...
                  X