суть проблемы: к МК 90S2313 подключен 7ми сегментный цифровой индикатор через сдвиговый регистр 74HC164, дабы не занимать лишние лапы.
цифра выводится на индикатор следующим образом:
выставляем на CLK ноль, подаем 1 или 0 (смотря что нужно) на вход DATA,выставляем на CLK единицу
и так восемь раз.
и здесь напрашивается цикл
Так вот никак не могу додуматься как выводить цифры в цикле (на Си, компилятор CodeVision)
Страница 1 из 1
Микроконтроллеры начинающим
#2
Отправлено 25 Январь 2007 - 03:49
Например, так:
Задержки расставлять по вкусу (и возможностям регистра), теоретически, должно работать и без них.
Есть и более оптимальные варианты (сдвинуть число вправо и взять младший бит, двигать маску и т.д.)
А еще есть такая вещь, как 74HC595 - он напрямую к SPI цепляется.
for (i = 0; i < 8; i++) { CLK = 0; DATA = (number&(1 << i)) ? 0 : 1; CLK = 1; }
Задержки расставлять по вкусу (и возможностям регистра), теоретически, должно работать и без них.
Есть и более оптимальные варианты (сдвинуть число вправо и взять младший бит, двигать маску и т.д.)
А еще есть такая вещь, как 74HC595 - он напрямую к SPI цепляется.
#3
Отправлено 25 Январь 2007 - 10:59
вот про эту строчку можно по подробнее:
что она делает, что такое "number", "? 0 : 1;"-таких конструкций еще не встречал
DATA = (number&(1 << i)) ? 0 : 1;
что она делает, что такое "number", "? 0 : 1;"-таких конструкций еще не встречал
#4
Отправлено 26 Январь 2007 - 00:38
number - битовое значение, которое нужно вывести (в данном случае - восьмибитная маска, каждый бит в которой соответствует своему светодиоду).
1 << i - единица, сдвинутая на i бит влево (т.е., грубо говоря, получается двоичное число, где после 1 идет i нулей)
condition ? trueValue : falseValue - оператор, возвращающий trueValue если условие выполняется (применительно к C: condition - выражение, имеющее ненулевое значение), или falseValue, если условие не выполняется.
Т.е., выражение a = cond ? b : c; эквивалентно if (cond) a = b; else a = c; (только гораздо компактнее записывается).
Т.е., сдвигом (<<) мы получаем битовую маску - число с одной единицей, которая последовательно сдвигается в цикле справа налево. Затем мы делаем "AND" с состояниями светодиодов. Если в этом значении для i-того светодиода стоит 1, то условие выполняется и в DATA записывается "1", иначе - "0".
1 << i - единица, сдвинутая на i бит влево (т.е., грубо говоря, получается двоичное число, где после 1 идет i нулей)
condition ? trueValue : falseValue - оператор, возвращающий trueValue если условие выполняется (применительно к C: condition - выражение, имеющее ненулевое значение), или falseValue, если условие не выполняется.
Т.е., выражение a = cond ? b : c; эквивалентно if (cond) a = b; else a = c; (только гораздо компактнее записывается).
Т.е., сдвигом (<<) мы получаем битовую маску - число с одной единицей, которая последовательно сдвигается в цикле справа налево. Затем мы делаем "AND" с состояниями светодиодов. Если в этом значении для i-того светодиода стоит 1, то условие выполняется и в DATA записывается "1", иначе - "0".
#5
Отправлено 26 Январь 2007 - 10:46
додумался пока только до этого
какие ошибки?
и еще: подскажите про BCD (двоично-десятичная кодировку) - где почитать, что эт такое и т.п.
PS Большое спасибо за ответы
#include <90s2313.h> #include <delay.h> //знакогенератор пишем в EEPROM дабы не занимать регистры flash unsigned char zg7[10]={0xDB,0x48,0xE3,0xEA,0x78,0xBA,0xBB,0xC8,0xFB,0xFA}; unsigned char cnt, buf; void main(void) { PORTD=0x70; DDRD=0x60; // настройка портов. динамическая индикация пока не нужна PORTB=0x07; DDRB=0xFF; // поэтому сразу даем GND на нужный катод buf = zg7[3]; //Записываем нужное число из знакогенератора в переменную buf для отображения for (cnt=0;cnt<8;cnt++) { PORTD.6=0; //даем 0 на CLK if (buf & (1<<7)) {PORTD.5=1;} //проверяем флаг сдвига если установлен, в DATA пишем 1 else {PORTD.5=0;} //иначе пишем 0 в DATA PORTD.6=1; //даем 1 на CLK buf = buf << 1; // делаем логический сдвиг значения из знакогенератора } //for } //main
какие ошибки?
и еще: подскажите про BCD (двоично-десятичная кодировку) - где почитать, что эт такое и т.п.
PS Большое спасибо за ответы

#6
Отправлено 28 Январь 2007 - 13:17
Day
Второй сдвиг лишний. Т.е. биты выводятся не все, а через один.
В таком виде правильнее будет так:
BCD - форма записи, когда в байте хранится число от 0 до 99 - т.е. в каждых 4х битах - цифра от 0 до 9. (В младших 4х битах - единицы, в старших - десятки) Используется как раз для вывода на всякие числовые индикаторы.
http://en.wikipedia....y-coded_decimal
Второй сдвиг лишний. Т.е. биты выводятся не все, а через один.
В таком виде правильнее будет так:
for (cnt=0;cnt<8;cnt++) { PORTD.6=0; //даем 0 на CLK PORTD.5 = buf&1; // выводим в DATA младший бит buf >>= 1; // сдвигаем buf на бит вправо PORTD.6=1; //даем 1 на CLK } //for
BCD - форма записи, когда в байте хранится число от 0 до 99 - т.е. в каждых 4х битах - цифра от 0 до 9. (В младших 4х битах - единицы, в старших - десятки) Используется как раз для вывода на всякие числовые индикаторы.
http://en.wikipedia....y-coded_decimal
#7
Отправлено 31 Январь 2007 - 10:16
выкладываю то что получилось.
Ваши замечания господа!
PS Приветствуются камни большие и маленькие
#include <90s2313.h> #include <delay.h> #include <BCD.h> // МАКРОСЫ #define vbit_(n) (1<<n) //вес бита по номеру #define bits(p,b) (p |= (1<<b)) // устанавливает бит b в регистре p #define bitc(p,b) (p &= (~(1<<b))) // очищает бит b в регистре p #define checkbit(p,b) (p & (1<<b)) // проверка бита b в регистре p #define invertbit(xbyte, xbit) (xbyte^=(1<<xbit)) // инвертировать бит X в байте Y #define IND_DATA 5 #define IND_CLK 6 #define IND_KEYS 4 #define RELAY 4 //знакогенератор пишем в EEPROM дабы не занимать RAM, записаны цифры от 0 до 9 flash unsigned char zg7[10]={0xDB,0x48,0xE3,0xEA,0x78,0xBA,0xBB,0xC8,0xFB,0xFA}; unsigned char cnt, buf, sec; unsigned char bin2bcd(unsigned char n); interrupt [TIM1_OVF] void timer1_ovf_isr(void) //описываем прерывание { TCNT1H = 0x98; TCNT1L = 0x94; // снова устанавливаем временной интервал т.е. с какого значения таймер начинает считать // выполняемый код if (sec==59){sec=0;} else sec++;} void main(void) { PORTD=0x70; DDRD=0x60; // настройка портов. динамическая индикация пока не нужна PORTB=0x0f; DDRB=0xFF; // поэтому сразу даем GND на нужный катод //устанавливаем начальные параметры счетчика TCCR1A = 0b00000000; TCCR1B = 0b00000100; /* устанавливаем частоту клоков CR/256, те при кварце 10Мгц, CR/256 и начале отсчета от 0x9894 прерывания будут происходить через примерно 1сек*/ TCNT1H = 0x98; TCNT1L = 0x94; /* устанавливаем начальный временной интервал т.е. с какого значения таймер начинает считать в данном примере начинаем считать с 0x00ff */ OCR1H = 255; OCR1L = 250; /*устанавливаем регистр совпадения те при насчете таймером такого же значения должно произойти прерывание*/ TIMSK = 0b10000000; /* разрешаем прерывание от таймера/счетчика 1 по переполнению (бит7) и/или совпадению (бит6) в данном конкретном примере только по переполнению*/ #asm ("SEI") // ГЛОБАЛЬНО разрешаем прерывания while (1){ buf=zg7[(bin2bcd(sec) & 0x0f)]; //получаем единицы sec for (cnt=0;cnt<8;cnt++) { buf = buf << 1; // делаем логический сдвиг значения из знакогенератора bitc(PORTD,IND_DATA); if (SREG&0x01) {bits(PORTD,IND_DATA);} //проверяем флаг сдвига, если установлен, в DATA пишем 1 bitc(PORTD,IND_CLK); //даем 0 на CLK bits(PORTD,IND_CLK); //даем 1 на CLK } //for PORTB.3=0; delay_ms(1); PORTB.3=1; buf=zg7[((bin2bcd(sec)>>4) & 0x0f)]; //получаем десятки sec for (cnt=0;cnt<8;cnt++) { buf = buf << 1; // делаем логический сдвиг значения из знакогенератора bitc(PORTD,IND_DATA); if (SREG&0x01) {bits(PORTD,IND_DATA);} //проверяем флаг сдвига, если установлен, в DATA пишем 1 bitc(PORTD,IND_CLK); //даем 0 на CLK bits(PORTD,IND_CLK); //даем 1 на CLK } //for PORTB.2=0; delay_ms(1); PORTB.2=1; }//while } //main
Ваши замечания господа!
PS Приветствуются камни большие и маленькие
Поделиться темой:
Страница 1 из 1