佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 1901|回复: 11

[PIC]7Segment顯示

[复制链接]
chanian 该用户已被删除
发表于 11-3-2006 03:15 PM | 显示全部楼层 |阅读模式
我做的是一個用 PIC16F877A 的溫度顯示器,想問大家要怎樣把運算出來的數字分別用3個/4個 7 segment 顯示出來。

我的圖如下:



我是用 CCS 來寫,現在我的code是醬。。。

//上下限為 10 'C 到 110 'C
//delay() 為 delay_us(5000)
//Digit Lookup Table,
//byte CONST LED_MAP[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

while(1){

temp_sensor = read_adc();
delay_ms(10);
       
        if ( bread >=0x1f && bread <=0x51){
        temp=(2*temp_sensor)-52; //Gorvening Equation (Calibrated)
       
                if ((temp/0x64) >=1)
                        temp100s = 0x01; //百位運算
                else temp100s = 0;
                               
                temp10s = temp/0x0A;  //十位運算
                if (temp10s >= 10)
                        temp10s = temp10s - 0x0A;
               
                temp1s = temp%0x0A;  //個位運算
               
                //**啓動風扇的 code???

               
                for(counter=0;counter<50;counter++){  //7segment 顯示
                                port_b= led_map[temp100s]; //Digit 100's
                                port_c= 0x01;
                                delay();

                                port_b= led_map[temp10s]; //Digit 10's
                                port_c= 0x02;
                                delay();

                                port_b= led_map[temp1s]; //Digit 1's
                                port_c= 0x04;
                                delay();
                }

        }
        else {
                port_b= 0x79;
                port_c= 0x01;
                delay();

                port_b= 0x50;
                port_c= 0x06;
                delay();
        }


}

不知道醬子寫的話,正確嗎?我是有試過用了,可以正常顯示,只是我想一定會有更好的解決的方法吧。

另外,我要加入另一個 function 是說,如果我要在 溫度 高達 50 度時開動一組風扇,不知要從哪裏下手好。
我試過把 code  (**) 加到上面的 code 裏,問題是溫度達到了,風扇也開了,不過顯示沒有了。過後,顯示有回了,風扇卻停了~~

如果用 ccs 可以寫同一時間,作兩种動作的話。。。請大家教教我啊~~謝謝!
回复

使用道具 举报


ADVERTISEMENT

发表于 11-3-2006 04:55 PM | 显示全部楼层
http://www.ccsinfo.com/forum/viewtopic.php?t=25649&highlight=segment




  1. Code:

  2. /*
  3. *********************************************************************************************************
  4. *
  5. *                                     Multiplexed LED Display Driver
  6. *                   Reference: Jean J. Labrosse, Embedded Systems Building Blocks
  7. *
  8. * Filename   : LED.C
  9. * Programmer : John Leung (www.TechToys.com.hk)
  10. * Remarks    : Modified for PIC16-LEDSTK1
  11. * Date       : First version 1.0 on 19th Nov 2004
  12. * Language    : CCS C complier for PIC mid-range MCU, PCM version 3.170, under MPLAB IDE 7.01
  13. * Hardware   : PCB 11OCT2004.001, MCU is Microchip's PIC16F877a
  14. * History    : Modified for PIC16-LEDSTK1 dated 12 Jan 2006
  15. *********************************************************************************************************
  16. *                                              DESCRIPTION
  17. *
  18. * This module provides an interface to a multiplexed "7-segments x N digits" LED matrix.
  19. *
  20. * To use this driver:
  21. *
  22. *     1) To use this module, the following parameters under define (LED.H):
  23. *
  24. *        DISP_N_DIG          The total number of segments to display, inc. dp status
  25. *        DISP_N_SS           The total number of seven-segment digits (modules)
  26. *        DISP_PORT1_DIG      The address of the DIGITS   output port
  27. *        DISP_PORT_SEG       The address of the SEGMENTS output port
  28. *       first_dig_msk       The first digit mask for selecting the most significant digit
  29. *
  30. *     2) Allocate a hardware timer which will interrupt the CPU at a rate of at least:
  31. *
  32. *        DISP_N_DIG * 60  (Hz)
  33. *
  34. *********************************************************************************************************
  35. */

  36. /*
  37. *********************************************************************************************************
  38. *                                            LOCAL VARIABLES
  39. *********************************************************************************************************
  40. */

  41. //Remarks: The original Jean's code uses static for local variables; however, this is not valid
  42. //for CCS PICC complier as "static" has no effect under CCS C.

  43. static   INT16U DispDigMsk;            /* Bit mask used to point to next digit to display  */
  44. static   INT8U  DispSegTbl[DISP_N_SS]; /* Segment pattern table(buffer) for each digit to display, first entry the left most*/
  45. static   INT8U  DispSegTblIx;         /* Index into DispSegTbl[] for next digit to display */

  46. /*$PAGE*/
  47. /*
  48. *********************************************************************************************************
  49. *                             ASCII to SEVEN-SEGMENT conversion table
  50. *                                                             a
  51. *                                                           ------
  52. *                                                        f |      | b
  53. *                                                          |  g   |
  54. * Note: The segments are mapped as follows:                 ------
  55. *                                                        e |      | c
  56. *        a    b    c    d    e    f    g                   |  d   |
  57. *        --   --   --   --   --   --   --   --              ------
  58. *        D7   D6   D5   D4   D3   D2   D1   D0 (Using PORTD of 16F877a as the segments output port)
  59. *********************************************************************************************************
  60. */

  61. const INT8U DispASCIItoSegTbl[] = {// ASCII to SEVEN-SEGMENT conversion table
  62.     0x00,       // ' '
  63.     0x00,       // '!', No seven-segment conversion for exclamation point
  64.     0x44,       // '"', Double quote
  65.     0x00,       // '#', Pound sign
  66.     0x00,       // '$', No seven-segment conversion for dollar sign
  67.     0x00,       // '%', No seven-segment conversion for percent sign
  68.     0x00,       // '&', No seven-segment conversion for ampersand
  69.     0x40,       // ''', Single quote
  70.     0x9C,       // '(', Same as '['
  71.     0xF0,       // ')', Same as ']'
  72.     0x00,       // '*', No seven-segment conversion for asterix
  73.     0x00,       // '+', No seven-segment conversion for plus sign
  74.     0x00,       // ',', No seven-segment conversion for comma
  75.     0x02,       // '-', Minus sign
  76.     0x00,       // '.', No seven-segment conversion for period
  77.     0x00,       // '/', No seven-segment conversion for slash
  78.     0xFC,       // '0'
  79.     0x60,       // '1'
  80.     0xDA,       // '2'
  81.     0xF2,       // '3'
  82.     0x66,       // '4'
  83.     0xB6,       // '5'
  84.     0xBE,       // '6'               
  85.     0xE0,       // '7'
  86.     0xFE,       // '8'
  87.     0xF6,       // '9'
  88.     0x00,       // ':', No seven-segment conversion for colon
  89.     0x00,       // ';', No seven-segment conversion for semi-colon  
  90.     0x00,       // '<', No seven-segment conversion for less-than sign
  91.     0x12,       // '=', Equal sign
  92.     0x00,       // '>', No seven-segment conversion for greater-than sign
  93.     0xCA,       //'?', Question mark
  94.     0x00,       // '@', No seven-segment conversion for commercial at-sign  
  95.     0xEE,       // 'A'
  96.     0x3E,       // 'B', Actually displayed as 'b'
  97.     0x9C,       // 'C'               
  98.     0x7A,       // 'D', Actually displayed as 'd'
  99.     0x9E,       // 'E'
  100.     0x8E,       // 'F'
  101.     0xBC,       // 'G', Actually displayed as 'g'
  102.     0x6E,       // 'H'   
  103.     0x60,       // 'I', Same as '1'
  104.     0x78,       // 'J'                    
  105.     0x00,       // 'K', No seven-segment conversion         
  106.     0x1C,       // 'L'                                      
  107.     0x00,       // 'M', No seven-segment conversion            
  108.     0x2A,       // 'N', Actually displayed as 'n'      
  109.     0xFC,       // 'O', Same as '0'                     
  110.     0xCE,       // 'P'                                    
  111.     0x00,       // 'Q', No seven-segment conversion        
  112.     0x0A,       // 'R', Actually displayed as 'r'                  
  113.     0xB6,       // 'S', Same as '5'                          
  114.     0x1E,       // 'T', Actually displayed as 't'              
  115.     0x7C,       // 'U'                                    
  116.     0x00,       // 'V', No seven-segment conversion         
  117.     0x00,       // 'W', No seven-segment conversion        
  118.     0x00,       // 'X', No seven-segment conversion        
  119.     0x76,       // 'Y'                                    
  120.     0x00,       // 'Z', No seven-segment conversion      
  121.     0x00,       // '['                              
  122.     0x00,       // '\', No seven-segment conversion  
  123.     0x00,       // ']'                                
  124.     0x00,       // '^', No seven-segment conversion   
  125.     0x00,       // '_', Underscore                        
  126.     0x00,       // '`', No seven-segment conversion for reverse quote
  127.     0xFA,       // 'a'                                      
  128.     0x3E,       // 'b'                                      
  129.     0x1A,       // 'c'                                    
  130.     0x7A,       // 'd'                                 
  131.     0xDE,       // 'e'                           
  132.     0x8E,       // 'f', Actually displayed as 'F'  
  133.     0xBC,       // 'g'                          
  134.     0x2E,       // 'h'                                 
  135.     0x20,       // 'i'                                            
  136.     0x78,       // 'j', Actually displayed as 'J'              
  137.     0x00,       // 'k', No seven-segment conversion            
  138.     0x1C,       // 'l', Actually displayed as 'L'            
  139.     0x00,       // 'm', No seven-segment conversion        
  140.     0x2A,       // 'n'                                
  141.     0x3A,       // 'o'                              
  142.     0xCE,       // 'p', Actually displayed as 'P'        
  143.     0x00,       // 'q', No seven-segment conversion   
  144.     0x0A,       // 'r'                                 
  145.     0xB6,       // 's', Actually displayed as 'S'         
  146.     0x1E,       // 't'                    
  147.     0x38,    // 'u'
  148.     0x00,    // 'v', No seven-segment conversion
  149.     0x00,    // 'w', No seven-segment conversion
  150.     0x00,    // 'x', No seven-segment conversion
  151.     0x76,    // 'y', Actually displayed as 'Y'              
  152.     0x00     // 'z', No seven-segment conversion
  153. };


  154. /*
  155. *********************************************************************************************************
  156. *                                          CLEAR THE DISPLAY
  157. *
  158. * Description: This function is called to clear the display.
  159. * Arguments  : none
  160. * Returns    : none
  161. *********************************************************************************************************


复制代码
回复

使用道具 举报

chanian 该用户已被删除
 楼主| 发表于 11-3-2006 07:23 PM | 显示全部楼层
哇 很長哩~ 不過還是謝謝!

要慢慢看了~
回复

使用道具 举报

发表于 12-3-2006 02:47 PM | 显示全部楼层
原帖由 chanian 于 11-3-2006 03:15 PM 发表
我試過把 code  (**) 加到上面的 code 裏,問題是溫度達到了,風扇也開了,不過顯示沒有了。過後,顯示有回了,風扇卻停了~~

如果用 ccs 可以寫同一時間,作兩种動作的話。。。請大家教教我啊~~謝謝!

你可以加一个timer0 的 interrupt,让它自动刷新7seg 。
请告诉我效果如何。

p/s: 我很乐意帮助能互动交流的网友,告诉我结果,不管我提供的方法可不可行,因为我也在从中学习。

[code]
int fDisp;

void display7Seg()
{

   if(fDisp)
   {
   //7segment 顯示
      port_b= led_map[temp100s]; //Digit 100's
      port_c= 0x01;
      delay();
      
      port_b= led_map[temp10s]; //Digit 10's
      port_c= 0x02;
      delay();
      
      port_b= led_map[temp1s]; //Digit 1's
      port_c= 0x04;
      delay();
   
   }
   else
   {   
      port_b= 0x79;
      port_c= 0x01;
      delay();
      port_b= 0x50;
      port_c= 0x06;
      delay();
   }

}

// Timer 0 Interrupt
#int_rtcc
void Timer0_Interrupt()
{
   display7Seg();
}


void main()
{

   setup_counters( RTCC_INTERNAL, RTCC_DIV_64);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   while(1)
   {
   
      temp_sensor = read_adc();
      delay_ms(10);
           
        if ( bread >=0x1f && bread <=0x51)
        {
           temp=(2*temp_sensor)-52; //Gorvening Equation (Calibrated)
        
             if ((temp/0x64) >=1)
                     temp100s = 0x01; //°&Ugrave;&Icirc;&raquo;&szlig;\&Euml;&atilde;
             else temp100s = 0;
                             
             temp10s = temp/0x0A;  //&Ecirc;&reg;&Icirc;&raquo;&szlig;\&Euml;&atilde;
             if (temp10s >= 10)
                     temp10s = temp10s - 0x0A;
            
             temp1s = temp%0x0A;  //&#8218;
回复

使用道具 举报

chanian 该用户已被删除
 楼主| 发表于 12-3-2006 05:08 PM | 显示全部楼层
原帖由 pic 于 12-3-2006 02:47 PM 发表

你可以加一个timer0 的 interrupt,让它自动刷新7seg 。
请告诉我效果如何。

p/s: 我很乐意帮助能互动交流的网友,告诉我结果,不管我提供的方法可不可行,因为我也在从中学习。

[code]
int fDisp;
...


嗯,我看今天試不了了。明天 要 測驗。
我是過後再回你了。

謝謝。

回复

使用道具 举报

发表于 13-3-2006 05:39 PM | 显示全部楼层
ccs我不懂~~

c2c我就懂!!
回复

使用道具 举报

Follow Us
chanian 该用户已被删除
 楼主| 发表于 14-3-2006 07:40 PM | 显示全部楼层
原帖由 pic 于 12-3-2006 02:47 PM 发表

你可以加一个timer0 的 interrupt,让它自动刷新7seg 。
请告诉我效果如何。

p/s: 我很乐意帮助能互动交流的网友,告诉我结果,不管我提供的方法可不可行,因为我也在从中学习。

[code]
int fDisp;
...



今天試過了。。。是算成功了

可是,我對這個 timer0 的 code 還是不太明白。。。
再給我一點時間,我想就可以 看得穿 了。
回复

使用道具 举报

chanian 该用户已被删除
 楼主| 发表于 15-3-2006 05:06 AM | 显示全部楼层
原帖由 pic 于 12-3-2006 02:47 PM 发表

你可以加一个timer0 的 interrupt,让它自动刷新7seg 。
请告诉我效果如何。

p/s: 我很乐意帮助能互动交流的网友,告诉我结果,不管我提供的方法可不可行,因为我也在从中学习。

[code]
int fDisp;
...


剛剛再改了一下。。。我把 timer0 的code 刪了。。。
然後把 display7seg() 分多一個 function, displayErr()

那個test condition 的部分放在上面, 在決定要display 7seg 還是 error...

while(1){
      temp_sensor = read_adc();
      delay_ms(10);
           
        if ( bread >=0x1f && bread <=0x51){
        temp=(2*temp_sensor)-52; //Gorvening Equation (Calibrated)
        
             if ((temp/0x64) >=1)
                 temp100s = 0x01; //百位運算
                          else temp100s = 0;
                             
             temp10s = temp/0x0A;  //十位運算
                          if (temp10s >= 10)
                 temp10s = temp10s - 0x0A;
            
             temp1s = temp%0x0A;  //個位運算
            

                          //模擬風扇開/関 port_d = 0x03, 開, =0, 関

             if (temp10s >= 5) //溫度大於50,或等於50
                 port_d=0x03; //Fan 開
             else port_d=0; // Fan 関

             display7seg(); //顯示溫度
         }
         else
             displayErr(); //錯誤顯示

}

void display7seg(){

                port_b= led_map[temp100s]; //Digit 100's
                port_c= 0x01;
                delay();

                port_b= led_map[temp10s]; //Digit 10's
                port_c= 0x02;
                delay();

                port_b= led_map[temp1s]; //Digit 1's
                port_c= 0x04;
                delay();

}

void displayErr(){

                port_b= 0x79;
                port_c= 0x01;
                delay();

                port_b= 0x50;
                port_c= 0x06;
                delay();
}


我醬子寫的話,比較簡單明白。。。看了整個晚上的 timer... 還不是很明白它的操作原理。。所以就擅自該了一些 code and test...

現在我想要的東西算是搞定了,不過我想那個timer0的東西應該在比較複雜的code裏會很有用處,所以學用它是逃不了的啦。

pic,好不好稍微講一下timer 的東西?或者,傳我一篇容易理解的 article?


回复

使用道具 举报


ADVERTISEMENT

发表于 15-3-2006 01:07 PM | 显示全部楼层
原帖由 chanian 于 15-3-2006 05:06 AM 发表
好不好稍微講一下timer 的東西?或者,傳我一篇容易理解的 article?
  ...


Timer 就是计时器,定时器。
Timer0,1,2 是PIC16F87X的timer。
Timer 0 是 8bit timer, 它的TMR0 register 会增加,
如果Clock是4Mhz, 那每(1/(4000000/4))1uS,  Timer0 就会加一。
(为什么除4?是因为PIC要4clock cycle 为一个intruction set)
从0-255,算到255->0时, interrupt就会发生, program 会跳去interupt的routine,做一些事,做完后会自动回去 。
那么每256uS, interrupt 就会发生, 可能太快了,我们可以set Clock prescaler,把Clock 除 prescaler,弄慢一点。
(4000000/(4*256))= 256uS/interrupt


这里,RTCC 就是Timer0, 是旧的CCS语法。
setup_counters( RTCC_INTERNAL, RTCC_DIV_64);
RTCC_DIV_64意思是把clock /64=  (4000000/(4*64*256))= 16384uS/interrupt= 16mS/interrupt
16384uS/interrupt= 16mS/interrupt= 62.5Hz

就是说, 每16mS 就会execute 一次 display7Seg(),
#int_rtcc
void Timer0_Interrupt()
{
   display7Seg();
}
你的void main( ) 可以不用管几时要update 7Seg,Timer会自动每16mS刷新一次。


enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
告诉compiler, 我们要使用Timer0/RTCC interrupt。
回复

使用道具 举报

chanian 该用户已被删除
 楼主| 发表于 15-3-2006 02:43 PM | 显示全部楼层
原帖由 pic 于 15-3-2006 01:07 PM 发表


Timer 就是计时器,定时器。
Timer0,1,2 是PIC16F87X的timer。
Timer 0 是 8bit timer, 它的TMR0 register 会增加,
如果Clock是4Mhz, 那每(1/(4000000/4))1uS,  Timer0 就会加一。
(为什么除4? ...


嗯,醬看來。。。

我只需要控制 fdisp 就可以決定要用那一組display了。。。

有一點我想弄清楚是說,是不是 不管我的 main() 有跑沒跑, timer 都會跟住它的時間跑。

timer0, timer1, 和 timer2 的用法和功能一樣嗎?
回复

使用道具 举报

发表于 16-3-2006 08:17 AM | 显示全部楼层
有一點我想弄清楚是說,是不是 不管我的 main() 有跑沒跑, timer 都會跟住它的時間跑。

是的,如果你的void main( )   没有进入 sleep state, timer0 interrupt & global interrupt 没有disable。
   
timer0, timer1, 和 timer2 的用法和功能一樣嗎?

timer0 & timer2 是8bit, timer1 是16bit,用法和功能有一点差异。你可以看datasheet。

要学好PIC MCU, 也要学会看DataSheet。
回复

使用道具 举报

chanian 该用户已被删除
 楼主| 发表于 18-3-2006 07:30 AM | 显示全部楼层
原帖由 pic 于 16-3-2006 08:17 AM 发表

是的,如果你的void main( )   没有进入 sleep state, timer0 interrupt & global interrupt 没有disable。
   

timer0 & timer2 是8bit, timer1 是16bit,用法和功能有一点差异。你可以看datash ...


今天再度改良。。。發現原來 timer0 interrupt 的時候,main() program 是沒有走, 直到 timer0 走完后,main() program 才繼續從剛才停留的地方再走。。。

我只是用software debugger 來進行分析,不知道准沒有~

另外,有辦法讓 PIC 在同一個時間進行兩組 function 嗎?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 28-11-2024 11:45 PM , Processed in 0.120331 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表