查看: 1901|回复: 11
|
[PIC]7Segment顯示
[复制链接]
|
|
我做的是一個用 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 可以寫同一時間,作兩种動作的話。。。請大家教教我啊~~謝謝! |
|
|
|
|
|
|
|
发表于 11-3-2006 04:55 PM
|
显示全部楼层
http://www.ccsinfo.com/forum/viewtopic.php?t=25649&highlight=segment
- Code:
- /*
- *********************************************************************************************************
- *
- * Multiplexed LED Display Driver
- * Reference: Jean J. Labrosse, Embedded Systems Building Blocks
- *
- * Filename : LED.C
- * Programmer : John Leung (www.TechToys.com.hk)
- * Remarks : Modified for PIC16-LEDSTK1
- * Date : First version 1.0 on 19th Nov 2004
- * Language : CCS C complier for PIC mid-range MCU, PCM version 3.170, under MPLAB IDE 7.01
- * Hardware : PCB 11OCT2004.001, MCU is Microchip's PIC16F877a
- * History : Modified for PIC16-LEDSTK1 dated 12 Jan 2006
- *********************************************************************************************************
- * DESCRIPTION
- *
- * This module provides an interface to a multiplexed "7-segments x N digits" LED matrix.
- *
- * To use this driver:
- *
- * 1) To use this module, the following parameters under define (LED.H):
- *
- * DISP_N_DIG The total number of segments to display, inc. dp status
- * DISP_N_SS The total number of seven-segment digits (modules)
- * DISP_PORT1_DIG The address of the DIGITS output port
- * DISP_PORT_SEG The address of the SEGMENTS output port
- * first_dig_msk The first digit mask for selecting the most significant digit
- *
- * 2) Allocate a hardware timer which will interrupt the CPU at a rate of at least:
- *
- * DISP_N_DIG * 60 (Hz)
- *
- *********************************************************************************************************
- */
- /*
- *********************************************************************************************************
- * LOCAL VARIABLES
- *********************************************************************************************************
- */
- //Remarks: The original Jean's code uses static for local variables; however, this is not valid
- //for CCS PICC complier as "static" has no effect under CCS C.
- static INT16U DispDigMsk; /* Bit mask used to point to next digit to display */
- static INT8U DispSegTbl[DISP_N_SS]; /* Segment pattern table(buffer) for each digit to display, first entry the left most*/
- static INT8U DispSegTblIx; /* Index into DispSegTbl[] for next digit to display */
- /*$PAGE*/
- /*
- *********************************************************************************************************
- * ASCII to SEVEN-SEGMENT conversion table
- * a
- * ------
- * f | | b
- * | g |
- * Note: The segments are mapped as follows: ------
- * e | | c
- * a b c d e f g | d |
- * -- -- -- -- -- -- -- -- ------
- * D7 D6 D5 D4 D3 D2 D1 D0 (Using PORTD of 16F877a as the segments output port)
- *********************************************************************************************************
- */
- const INT8U DispASCIItoSegTbl[] = {// ASCII to SEVEN-SEGMENT conversion table
- 0x00, // ' '
- 0x00, // '!', No seven-segment conversion for exclamation point
- 0x44, // '"', Double quote
- 0x00, // '#', Pound sign
- 0x00, // '$', No seven-segment conversion for dollar sign
- 0x00, // '%', No seven-segment conversion for percent sign
- 0x00, // '&', No seven-segment conversion for ampersand
- 0x40, // ''', Single quote
- 0x9C, // '(', Same as '['
- 0xF0, // ')', Same as ']'
- 0x00, // '*', No seven-segment conversion for asterix
- 0x00, // '+', No seven-segment conversion for plus sign
- 0x00, // ',', No seven-segment conversion for comma
- 0x02, // '-', Minus sign
- 0x00, // '.', No seven-segment conversion for period
- 0x00, // '/', No seven-segment conversion for slash
- 0xFC, // '0'
- 0x60, // '1'
- 0xDA, // '2'
- 0xF2, // '3'
- 0x66, // '4'
- 0xB6, // '5'
- 0xBE, // '6'
- 0xE0, // '7'
- 0xFE, // '8'
- 0xF6, // '9'
- 0x00, // ':', No seven-segment conversion for colon
- 0x00, // ';', No seven-segment conversion for semi-colon
- 0x00, // '<', No seven-segment conversion for less-than sign
- 0x12, // '=', Equal sign
- 0x00, // '>', No seven-segment conversion for greater-than sign
- 0xCA, //'?', Question mark
- 0x00, // '@', No seven-segment conversion for commercial at-sign
- 0xEE, // 'A'
- 0x3E, // 'B', Actually displayed as 'b'
- 0x9C, // 'C'
- 0x7A, // 'D', Actually displayed as 'd'
- 0x9E, // 'E'
- 0x8E, // 'F'
- 0xBC, // 'G', Actually displayed as 'g'
- 0x6E, // 'H'
- 0x60, // 'I', Same as '1'
- 0x78, // 'J'
- 0x00, // 'K', No seven-segment conversion
- 0x1C, // 'L'
- 0x00, // 'M', No seven-segment conversion
- 0x2A, // 'N', Actually displayed as 'n'
- 0xFC, // 'O', Same as '0'
- 0xCE, // 'P'
- 0x00, // 'Q', No seven-segment conversion
- 0x0A, // 'R', Actually displayed as 'r'
- 0xB6, // 'S', Same as '5'
- 0x1E, // 'T', Actually displayed as 't'
- 0x7C, // 'U'
- 0x00, // 'V', No seven-segment conversion
- 0x00, // 'W', No seven-segment conversion
- 0x00, // 'X', No seven-segment conversion
- 0x76, // 'Y'
- 0x00, // 'Z', No seven-segment conversion
- 0x00, // '['
- 0x00, // '\', No seven-segment conversion
- 0x00, // ']'
- 0x00, // '^', No seven-segment conversion
- 0x00, // '_', Underscore
- 0x00, // '`', No seven-segment conversion for reverse quote
- 0xFA, // 'a'
- 0x3E, // 'b'
- 0x1A, // 'c'
- 0x7A, // 'd'
- 0xDE, // 'e'
- 0x8E, // 'f', Actually displayed as 'F'
- 0xBC, // 'g'
- 0x2E, // 'h'
- 0x20, // 'i'
- 0x78, // 'j', Actually displayed as 'J'
- 0x00, // 'k', No seven-segment conversion
- 0x1C, // 'l', Actually displayed as 'L'
- 0x00, // 'm', No seven-segment conversion
- 0x2A, // 'n'
- 0x3A, // 'o'
- 0xCE, // 'p', Actually displayed as 'P'
- 0x00, // 'q', No seven-segment conversion
- 0x0A, // 'r'
- 0xB6, // 's', Actually displayed as 'S'
- 0x1E, // 't'
- 0x38, // 'u'
- 0x00, // 'v', No seven-segment conversion
- 0x00, // 'w', No seven-segment conversion
- 0x00, // 'x', No seven-segment conversion
- 0x76, // 'y', Actually displayed as 'Y'
- 0x00 // 'z', No seven-segment conversion
- };
- /*
- *********************************************************************************************************
- * CLEAR THE DISPLAY
- *
- * Description: This function is called to clear the display.
- * Arguments : none
- * Returns : none
- *********************************************************************************************************
-
复制代码 |
|
|
|
|
|
|
|
楼主 |
发表于 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; //°Ùλß\Ëã
else temp100s = 0;
temp10s = temp/0x0A; //ʮλß\Ëã
if (temp10s >= 10)
temp10s = temp10s - 0x0A;
temp1s = temp%0x0A; //‚ |
|
|
|
|
|
|
|
楼主 |
发表于 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
|
显示全部楼层
|
|
|
|
|
|
|
楼主 |
发表于 14-3-2006 07:40 PM
|
显示全部楼层
|
|
|
|
|
|
|
楼主 |
发表于 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?
|
|
|
|
|
|
|
|
发表于 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。 |
|
|
|
|
|
|
|
楼主 |
发表于 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。 |
|
|
|
|
|
|
|
楼主 |
发表于 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 嗎? |
|
|
|
|
|
|
| |
本周最热论坛帖子
|