Примеры с сайта AVR+ Electronics

Автор: Internet. Опубликовано в Начинающим CV AVR

Содержание материала

AVR и регистр сдвига 74HC164.

Сегодня поговорим о регистрах сдвига (shift registr) на примере 74HC164. Бывают ситуации, когда у МК не хватает свободных портов, особенно если в устройстве используется светодиодная индикация, тогда и можно использовать регистр сдвига. Да, они широко используются и в бытовой аппаратуре для работы с дисплеем. Немного теории… Из управляющих входов у нас есть: DATA, RESET, CLK ,а на выходе мы получаем 8-выходов. Немного о назначение входов. О пине RESET – сброс установленных значений на выходе, обычно не используется, так как занимает лишний пин у МК. Он должен всегда быть поднятым, для этого подрубаем его к Vcc, а сбрасывать значение будем посылкой 8бит лог.1 О пине CLK – этим пином продвигаем значение по регистру. DATA – собственно сами данные о значение следующего выхода. Плавно подходим к заполнению регистра. Для заполнения регистра выполняем такую последовательность:

1. выдаём первый старший бит из пачки на линию DATA

2. опускаем в лог. 0 линию CLC

3. поднимаем в лог.1 линию CLC

4. повторяем все пункты с 1, пока не выдадим все биты.

Для сброса, просто запускаем новые 8бит данных. Для наглядности можно собрать это всё в Proteus и потыкать кнопочками. Думаю теории хватит, перейдём к практике. Для наглядного примера я собрал такой девайс на Тини13, который выводит числа от 0 до 99 на 2х разрядном 7-ми сегментном LED дисплее. Так как Тини13 сам зажечь дисплей не сможет, поставил я ему в помощь 74HC164.

Вот схема:


На программе останавливаться не буду, так как в исходниках всё предельно ясно. Исходники на Си. Скачать можно тут ain.zip (исходный код, прошивка,  proteus).

Вот собственно и всё, надеюсь кому-то пригодиться.

Code
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Author          : Krik99
Chip type       : ATtiny13
Clock frequency : 9.6MHz
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include <tiny13.h>
#include     
char digit_out[2], cur_dig;
flash char buf[] = {     //массив с цифрами
0b00000011, //0
0b10011111, //1 
0b00100101, //2
0b00001101, //3
0b10011001, //4
0b01001001, //5
0b01000001, //6
0b00011111, //7
0b00000001, //8
0b00001001, //9
0b11111111
};        
     
void hc164_wr(unsigned char dig){  //подпрограмма вывода данных в регистр
unsigned char a;
 for(a=0; a<8; a++){            //цикл для вывода 8 бит данных из массива
   PORTB.0 = buf[dig] & 1<<a; <span="" data-mce-bogus="1" class="mceItemHidden mceItemNbsp">  //выводим в линию DATA текущий бит 
   PORTB.1=0;         //опускаем линию CLK в лог.0
   PORTB.1=1;         //поднимаем линию CLK в лог.1
 }
}    
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{                              
switch (cur_dig){   
case 0:{PORTB.3=0; PORTB.2=0; hc164_wr(digit_out[cur_dig]); PORTB.2=1; break;};  //первая цифра
case 1:{PORTB.2=0; PORTB.3=0; hc164_wr(digit_out[cur_dig]); PORTB.3=1; break;};  //вторая цифра
}                          
cur_dig++;                        
if (cur_dig==2) cur_dig=0; 
}           
void main(void)
{   
unsigned char f;
// Port B initialization
PORTB=0x00;
DDRB=0xFF; 
// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x03;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;
// Global enable interrupts
#asm("sei") 
while (1){ 
   for(f=0; f<100; f++){ 
   delay_ms(50);
   digit_out[0]=f/10;
   digit_out[1]=f%10;
   }
      };
}