Thông báo

Collapse
No announcement yet.

tutorial cho HTPIC

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

  • tutorial cho HTPIC

    Việc tìm hiểu ban đầu để viết một chương trình bằng HTPIC có vẻ hơi mới mẻ với newbie. Bác nào có kinh nghiệm ...viết một chút tutorial để cho newbie như em có thể tiếp cận được nhanh hơn ko ah? Nếu không có tutorial thì các bác post mấy cái code đơn giản lên để bọn em nghiền ngẫm và tự rút ra cách để viết chương trình.

    Em nghĩ như vậy sẽ tốt hơn cho những ai mới viết chương trình bằng HTPIC
    Hi vọng bài viết giúp X được cho bạn.

  • #2
    Chuẩn để viết HTPIC là chuẩn ANSI- C bạn ạ.

    Giống như với Keil C. Trong HTPIC các thanh ghi, các port đã được định nghĩa bằng các từ khóa # define hết rồi. Bạn nên mở một file .h header file ra nghiên cứu thì sẽ thấy cấu trúc của một file .h như sau:

    - Phần đầu tiên là liệt kê các chíp PIC sử dụng file này. Vì mỗi loại PIC khác nhau thì địa chỉ trong bộ nhớ khác nhau.

    - Phần 2 định nghĩa các port, các thanh ghi, .. Điều đặc biệt là tên của các port, thanh ghi, ... hoàn toàn giống hệt như trong datasheet ấy.

    Ví dụ , viết với PIC16F877A thì bạn mở file pic16f87x.h ra xem.
    Sau đó mở datasheet ra, đọc từng phần một như I/O port, Timer,AD, ... sau đó tìm hiểu các thanh ghi trong đó rồi lập trình với các thanh ghi đó(đã định nghĩa hết).

    Bạn nên mở các ví dụ, trong thư mục example ra xem có code mẫu là những modul nhỏ dạng file

    Chúc bạn thành công. Tôi sẽ viết chi tiết những cái gì mà tôi biết, học được. Hi vọng là sẽ giúp cho các bạn hiểu được.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

    Comment


    • #3
      Nháy 8 led

      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.
      Last edited by ngohaibac; 20-03-2006, 19:12.
      Technical sale at WT Microelectronics S'pore
      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

      Comment


      • #4
        Đây là chương trình dùng ngắt timer0.

        Code:
        #include<pic.h>
        
        __CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
        
        //================================================================
        // Hàm ng?t Timer0
        void interrupt inter0(void){
        	static unsigned char i;
        	static unsigned int counter; // bien dem su kien ngat timer0
        	if(T0IF & T0IE){ // neu co ngat Timer0 xay ra
        		TMR0 = 6;
        		T0IF = 0 ; 
        // xoa co ngat, cong viec khong the thieu sau ham ngat
        		++	counter;
        		if(counter == 500){
        			PORTD = (1<<i) + (1<<(7-i));
        			++i;
        			if(i==8) i=0;
        			counter = 0;
        		};
        	};
        }
        
        // == Ham khoi tao cho chip PIC16F877A
        void init(void){
        	// Khoi tao I/O cho cac port
        	TRISD = 0x00;// PortD as output
        	
        	// Khoi tao cho cac thanh ghi	
        	OPTION  = 0x00; // dung prescaler cho timer0 voi ti le la 1:2
        
        	// Khoi tao cho ngat Timer0
        	GIE = 1; // cho phep ngat toan cuc
        	T0IE = 1; // cho phep ngat timer0
        	T0IF = 0; // xoa co ngat
        	TMR0 = 6; // khoi tao
        }
        
        // Chuong trinh chinh
        void main(void){
        	 init();
        	while(1);
         // de con tro PC khong nhay lung tung,con lam gi thi lam :D
        }
        Thuật giải của chương trình dùng ngắt đó là: dùng một biến tĩnh kiểu static để đếm số lần xuất hiện ngắt timer0.

        Trong chương trình này mình sau 500 ngắt timer0 thì mới quét led1 lần.

        Ngoài ra cũng dùng thêm biến static i để biết được đang quét led nào. Do đó dùng ngắt sẽ tiện hơn nhiều. Và dùng đếm sự kiện ngắt thì ta có thể không cần dùng Prescaler với tỉ lệ quá cao, tránh được sai số nhiều.

        Không biết mọi người có ý kiến thế nào?
        Last edited by ngohaibac; 22-03-2006, 15:30.
        Technical sale at WT Microelectronics S'pore
        Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
        Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

        Comment


        • #5
          Tiếp theo tôi xin đưa cho mọi người xem một chương trình của tui không biết liệu nó đã tối ưu chưa? Đã hiệu quả chưa?

          Mô tả phần cứng: có 4 led 7 thanh. Các chân của PORTD 7->0 nối với 8 con trở 220 Ohm nối với các chân a->g của led7. Các chân RA5 đến RA3 nối với 4 con trở 4.7k Ohm rồi nối vào cực bazơ của con uA1015 lần lượt nối với các cực Anot của 4 led.

          Đây là sch: vì to quá nên cắt thành 2 nhìn cho rõ:




          Yêu cầu của chương trình là: hiển thị ra 4 led các giá trị tăng dần từ 0000 đến 9999 sau đó lại quay lại.

          Chương trình này lấy phần giải mã của anh 4MD. chương trình của anh ấy dùng cả delay. Nhưng tôi nghĩ là khi dùng ngắt rùi thì dùng delay làm gì cho phí. Do đó việc dùng ngắt làm cho ta đỡ tốn thời gian làm những việc linh tinh.

          Các bạn cho ý kiến về giải thuật này.

          Code:
          #include<pic.h>
          const unsigned char Font[]={ 0b00000011, 0b1001111, 0b00100101,\ 0b00001101, 0b10011001,	0b01001001, 0b01000001,\
           0b00011111, 0b00000001, 0b00001001};
          
          __CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
          
          //------------------------------------Interrupt
          void interrupt MyInt(void){
          	static int counter1,counter2;
          	// counter1 đếm số  lần Timer0 tràn
          	// counter2  đếm số  lần cả bộ led được quét
          	static unsigned int number;
          	static unsigned int a[4]={0,0,0,0};
          	static unsigned char j;
          		if(T0IF & T0IE){	
          		        T0IF = 0 ;// xoa co ngat
                                  TMR0 = 6;
          			if(++ counter1 == 500){
          				counter1 = 0;
          				PORTD = 0xFF;
          				PORTA	= 0xFF - (1<<(5-j));// bat mot led
          				PORTD	= Font[a[j]];
          				if(++j==4) {
          					j=0;
          					++counter2;
          				};
          			};
          			if(counter2 == 500){
          				 ++number;
          				if(number>9999) number= 0;
          				counter2 = 0;
          				a[3] = number/1000;
          				a[2] = (number/100)%10;
          				a[1] = (number/10)%10;
          				a[0] = number%10;
          			};
          		};
          	}
          
          //------------------------------------init
          void init(void)
          	{
          		//-------------------------init for PORTs
          		OPTION = 0b00000000;
          		ADCON1 = 0b00000111;
          		TRISA	= 0b00000000;
          		TRISB	= 0b11111111;
          		TRISC	= 0b11111111;
          		TRISD	= 0b00000000;
          		TRISE	= 0b11111111;
          		//-------------------------init for interrupt
          		GIE		= 1;
          		T0IE = 1;
          		TMR0 = 6;
          	}
          
          //------------------------------------MAIN
          void main(){
          	init();
          	while(1);  // Trong này làm gì thì làm
          }
          Anh 4MD cho ý kiến với em luôn.

          Tôi đã edit lại có sửa chữa một vài chỗ. Chương trình này đã được test và chạy ngon lành .

          Chúc các bạn thành công.
          Last edited by ngohaibac; 17-10-2006, 21:44. Lý do: Edit lại hình ảnh
          Technical sale at WT Microelectronics S'pore
          Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
          Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

          Comment


          • #6
            Chương trình của mình có cái hay là khi bạn vừa dùng ngắt Timer0 để quét led bạn vừa có thể tận dụng nó để làm việc khác nữa như đếm số lần quét hoặc là delay để làm cái gì đó.

            Cái này giống kiểu tiết kiệm chân vi điều khiển vậy
            Technical sale at WT Microelectronics S'pore
            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

            Comment


            • #7
              Ông bạn viết phần chuyển đổi số "phu" quá. Viết như thế thì số dài n số thì có tới n lệnh chia.
              Tớ viết như sau:
              unsigned int a[3]; //cho so co 4 chu so
              unsigned int tg;
              {
              tg=number; //number la so can chuyen
              for(i=0;i<=3;i++)
              {
              a[3-i]=tg%10;
              tg=tg/10;
              }
              }

              Comment


              • #8
                Nguyên văn bởi ngohaibac
                Tiếp theo tôi xin đưa cho mọi người xem một chương trình của tui không biết liệu nó đã tối ưu chưa? Đã hiệu quả chưa?

                Mô tả phần cứng: có 4 led 7 thanh. Các chân của PORTD 7->1 nối với các chân a->g của led7. Các chân RA5 đến RA3 nối vào cực bazơ của con uA1015 lần lượt nối với các cực Anot của 4 led.

                Yêu cầu của chương trình là: hiển thị ra 4 led các giá trị tăng dần từ 0000 đến 9999 sau đó lại quay lại.

                Chương trình này lấy phần giải mã của anh 4MD. chương trình của anh ấy dùng cả delay. Nhưng tôi nghĩ là khi dùng ngắt rùi thì dùng delay làm gì cho phí. Do đó việc dùng ngắt làm cho ta đỡ tốn thời gian làm những việc linh tinh.

                Các bạn cho ý kiến về giải thuật này.

                Anh 4MD cho ý kiến với em luôn.

                Chúc các bạn thành công.
                Viết như thế cũng tàm tạm ổn, mô tả phần cũng thì cho con trở 2.2k trước khi vào chân B của trans, cho trở 220 trươc khi vào chân PIC.

                Viết chương trình dùng hàm delay có ưu điểm riêng của nó, nếu dùng ngắt timer thì tiện cho ứng dụng nhỏ, nếu bạn viết chương trình lớn thì 3 timer là hơi ít. Hơn nữa Timer2 dùng cho CCPx.

                Còn cách khác là lập trình multitasking, thân chương trình chính cũng là một hàm delay, ông bạn khá lập trình, nói thế chắc làm được ngay.

                Comment


                • #9
                  Cảm ơn Hòa đã góp ý cho tớ. Cái việc chia đó tất nhiên là có thể làm như cậu rùi vì cậu xem thuật toán chia cả 4 số đó là giống nhau. Đây là thuật toán giống như thuật toán đổi từ hệ cơ số 10 sang hệ cơ số 2 hình như là lớp 6 được học thì phải . Quên mất không khái quát nó lên. Thật tội lỗi quá . Mình đang cố gắng tối ưu hóa cái chương trình sao cho ngon lành nhất.

                  Hòa ơi, tớ vãn nghĩ là việc dùng hàm ngắt timer để xử lý nhiều việc muốn gây trễ vấn được nhưng quả thật nó có một điều không hay là nếu việc phải thực hiện nhiều thì sẽ dẫn đến liên tục thực hiện hàm ngắt như thế có thể gây tràn stack. Với các ứng dụng nhỏ như quét led, .. hoàn toàn có thể dùng cách này được, trong lúc quét led ta có thể làm được việc như là scan keypad,...

                  Còn việc lập trình Multitasking để nghĩ sau sẽ trả lời Hòa nha.

                  Chúc thành công.
                  Technical sale at WT Microelectronics S'pore
                  Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                  Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                  Comment


                  • #10
                    Nguyên văn bởi ngohaibac
                    Hòa ơi, tớ vãn nghĩ là việc dùng hàm ngắt timer để xử lý nhiều việc muốn gây trễ vấn được nhưng quả thật nó có một điều không hay là nếu việc phải thực hiện nhiều thì sẽ dẫn đến liên tục thực hiện hàm ngắt như thế có thể gây tràn stack. Với các ứng dụng nhỏ như quét led, .. hoàn toàn có thể dùng cách này được, trong lúc quét led ta có thể làm được việc như là scan keypad,...
                    Tại sao lại tràn stack được hả bạn? bởi khi vào ngắt cờ GIE tự động =0 rồi mà, khi thoát khỏi ngắt thì nó lại tự động =1; đây là do phần cứng của PIC. Nếu bạn dùng phần mềm bật GIE=1 thì khá nguy hiểm, cần nắm rõ nó.
                    PIC18 trở lên có thể ngắt trong ngắt.
                    Vấn đề nữa là hoàn toàn có thể làm vô số timer chạy song hành từ 1 timer gốc.

                    Comment


                    • #11
                      Cảm ơn Trang góp ý.

                      Khi dùng kiểu biến đếm sự kiện ngắt timer tất nhiên sẽ là như tạo ra các bộ timer chạy từ một timer gốc. Nhưng vấn đề ở thuật giải này chính là việc thực hiện trong hàm ngắt timer. Khi thực hiện trong hàm ngắt này, thời gian thực hiện lớn.

                      Timer0 là bộ free counter nên sau khi ngắt thì nó vẫn chạy. Khi chúng ta làm việc xóa cờ ngắt, khởi tạo timer0 trong hàm ngắt. Nếu thời gian thực hiện công việc lớn hơn thời gian một lần tràn timer0, khi đó TOIF có bật lên nhưng không thực hiện ngắt do GIE = 0, do đang xử lý ngắt. Như thế quả là không chính xác.

                      Nếu muốn xử lý chính xác thì chúng ta cần phải set GIE = 1 sau khi vào hàm ngắt. Khi đó sẽ có kiểu ngắt trong ngắt. Tuy việc này nguy hiểm nhưng nếu suy tính kĩ, disable các ngắt không cần thiết. Ví dụ đơn giản ở đây mình chỉ dùng ngắt Timer0 thôi thì chắc việc này không có vấn đề gì quá lớn. Khi mà các timer kiểu dẫn xuất đó (có chu kì ngắt = bội số của Timer0) có chu kì gần nhau, thực hiện chương trình với thời gian lớn thì dễ gây ra tràn stack lắm. Còn khi các việc cần thực hiện chỉ lớn hơn thời gian gây tràn của timer0 thì chúng ta có thể làm rất nhiều thứ chứ.

                      Bạn Trang nghĩ thế nào nhỉ?
                      Technical sale at WT Microelectronics S'pore
                      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                      Comment


                      • #12
                        Minh khong biet ban dang lam gi, nhung co dieu khi cau set gie =1, trong ngat doi voi timer0, voi hy vong khi timer0 tran thi xay ra ngat tran timer0. nhung co dieu luc do chuong trinh ngat dau da thuc hien song, minh lay vi du can lay giâ tri mot bien nao do trong chuong trinh ngat, ma khi chuong trinh trong ngat chua thuc hien song thi lam sao? minh hieu y cau la muon tan dung thoi gian trong khi timer dang hoat dong, chinh vi vay minh nghi la nen toi uu chuong trinh trong ngat de khong xay ra truong hop ma cau de cap den do, thong thuong cac chuong trinh trong ngat cung khong can phai qua dai, dieu do hoan toan khac phuc duoc khi xem xet chuong trinh nhu mot he thong hoan chinh de toi uu.
                        |

                        Comment


                        • #13
                          Bạn nên viết tiếng Việt cho dễ nhìn nha bạn.

                          Bạn đã hiểu ý mình. Điều quan trọng là tối ưu hóa chương trình thực hiện trong ngắt, tính toán làm sao cho hợp lý để có thể thực hiện chương trình kiểu ngắt trong ngắt.

                          Không biết bạn nào có cao kiến gì hơn nữa không đây? Theo mình thì khi dùng ngắt có thể giải quyết được mọi việc liên quan đến delay.
                          Technical sale at WT Microelectronics S'pore
                          Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                          Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                          Comment


                          • #14
                            Nguyên văn bởi minhpic1
                            Minh khong biet ban dang lam gi, nhung co dieu khi cau set gie =1, trong ngat doi voi timer0, voi hy vong khi timer0 tran thi xay ra ngat tran timer0.
                            Anh hãy thử đưa một chương trình có khoảng 3 ngắt, rồi anh bật GIE trong ngắt xem? em chưa thử cái này lần nào, nhưng tìm ra điểm sai của nó em lại làm được. Hihi...

                            Comment


                            • #15
                              Ý của "minhpic1" muốn nói là: Giả sử TIMER0 xãy ra ngắt trong 100us, nhưng khi nhãy vào ngắt, nếu chương trình ISR thực thi dài quá 100us thì việc set bit GIE=1 của "ngohaibac" sẽ làm cho một ngắt TIMNER nữa phát sinh (ngắt trong ngắt). Vậy thì nó sẽ xử lý như thế nào- đó là câu hỏi của bạn "minhpic1" đã hỏi ở trê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