#define IO_74HC164_SCK_HIGH io_74hc164_SCK = 1 ;
#define IO_74HC164_SCK_LOW io_74hc164_SCK = 0 ;
#define IO_74HC164_SDA_INPUT io_74hc164_SDA
下面是数码管的段码表可以根据不同的连接顺序去修改。
/***********************************************************
a -- 4 b -- 5 c -- 6 d -- 2
e -- 0 f -- 1 g -- 3 dp -- 7
***********************************************************/
uint8 code DisplayTable[]=
{
0x77,0x60,0x3D,0x7C,0x6A,0x5E,0x5F,0x70,0x7F,0x7E,0x7B,0x4F,0x17,0x6D,0x1F,0x1B,0x08/*0 1 2 3 4 5 6 7 8 9 a b c d e f - */
};
void v_74hc164WriteData_f( uint8 Dat ) //向74HC164写一个字节的内容
{ //即可并行输出该字节
uint8 i = 0 ;
uint8 SendData = Dat ;
for( i = 8 ; i > 0 ; i-- )
{
IO_74HC164_SCK_LOW
SendData <<= 1 ;
IO_74HC164_SDA_INPUT = CY ;
IO_74HC164_SCK_HIGH
}
}
void v_HexToBcd_f( uint8 *P, uint16 Dat ) //BCD码的转化
{
uint8 i = 0 ;
uint8 Temp ;
if( Dat >= 40000 ) { i = 4 ; Dat -= 40000 ; }
if( Dat >= 20000 ) { i += 2 ; Dat -= 20000 ; }
if( Dat >= 10000 ) { i += 1 ; Dat -= 10000 ; }
*P++ = i ;
i = 0 ;
if( Dat >= 8000 ) { i = 8 ; Dat -= 8000 ; }
if( Dat >= 4000 ) { i += 4 ; Dat -= 4000 ; }
if( Dat >= 2000 ) { i += 2 ; Dat -= 2000 ; }
if( Dat >= 1000 ) { i += 1 ; Dat -= 1000 ; }
*P++ = i ;
i = 0 ;
if( Dat >= 800 ) { i = 8 ; Dat -= 800 ; }
if( Dat >= 400 ) { i += 4 ; Dat -= 400 ; }
if( Dat >= 200 ) { i += 2 ; Dat -= 200 ; }
Temp = Dat ; //这里换成8位数据,是为了加快速度
if( Temp >= 100 ) { i += 1 ; Temp -= 100 ; }
*P++ = i ;
i = 0 ;
1) the best approach is to use 8 data pins (for 7 segments + dp) for all LEDs, and the turn each led on from one pin on hc164. so if you were to drive 16 leds, you need 2 hc164, driven by two pins (one for serial data + 1 for clock), + 8 pins.
2) if you cannot afford to have a 8 data pins, you can use another hc164, driven by two pins (again, one for serial data + 1 for clock) that deliver segment data to all LEDs, and another two pins to drive all the leds. so for a total of 16 leds, you need four data lines, and 3 leds: one for segment data, and two for 16 leds.作者: millwood0 时间: 2010-10-15 06:04
here is a quick demo of the concept.
it uses two hc164 to drive up to 8 7-segment leds (3 leds in our example).
=========code================
//using hc164 to drive common anode 7-segment leds
//each led is turned on by hc164
//for faster switching, consider using delay_us()
//this allows user to specify display duration for individual digits
const unsigned char code hc164_delay[8*HC164_MAX] = { //delay for each bit / led
10, //10ms delay for led0
10,
0,
0,
0,
0,
0,
0, //no delay if no led attached to that bit
0, //2nd hc164 starts here
0,
0,
10,
0,
0,
0,
0
};
unsigned char vRAM[8*HC164_MAX]="9100000000020000"; //to be displayed
void mcu_init(void) {
LED_OFF(); //turn off all leds
IO_OUT(LED_DDR, LED_PINs); //led_pins as output
int main(void) {
unsigned char i;
mcu_init(); //reset the mcu
while (1) {
LED_OFF(); //turn leds off
IO_SET(HC164_PORT, HC164_SDI); //send the initial 1
for (i=0; i<8*HC164_MAX; i++) {
HC164_STROBE(); //strobe the clk
//display char
LED_ON(ascii_table[vRAM-'0']);
delay_ms(hc164_delay); //some delay to allow the leds to be on
LED_OFF(); //turn off leds before shifting in the next digit
IO_CLR(HC164_PORT, HC164_SDI); //send the next bit
}
}
}
==========end===============作者: millwood0 时间: 2010-10-15 06:06
here is the simulation of it.
(原文件名:20. 7-segment HC164.PNG)
basically, the shift registers are only used to turn on individual 7-segment leds. the display data is put on P2 for all LEDs but since only one led is on at any given time, no cross-display of data on the wrong led.
the code can be easily modified to display more leds, or to drive led matrix - you just need to treat each column in a led matrix as one 7-segment led here.作者: millwood0 时间: 2010-10-15 06:08
this particular piece of code utilizes all of LED_PORT (P2 in this case) to display data. you obviously can use a shift register to do that, saving 8-2 pins.
all you need to change in that case is the LED_ON() macro, and the rest of the code remains the same.
obviously, this code is very portable to other mcus.作者: 284857914 时间: 2010-10-15 19:57
学习了,谢谢楼主啊。。。正在学习作者: intentydh 时间: 2010-10-18 17:48
mark作者: grant-liao 时间: 2010-12-2 16:28
楼主原来我看你的思路没明白
今天我明白了,但是我发现你把简单的东西讲的太复杂了。
其实就是串行中断的0方式,用作同步移位寄存器使用
也就是串行输入,并行输出,(需要有串入并出的移位寄存器如CD4049,74LS164,74HC164等)
或者是并行输入,串行输出。
需要注意的是数据是低位在前,高位在后。作者: clqfly 时间: 2010-12-2 16:55
mark作者: grant-liao 时间: 2011-1-24 11:00
状态机用的好啊
温故而知新啊
又看了一遍
还的慢慢消化作者: lajiao 时间: 2011-3-31 23:08
回复【楼主位】jchqxl 红金龙吸味
-----------------------------------------------------------------------