суть проблемы: к МК 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
} //forBCD - форма записи, когда в байте хранится число от 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

Помощь













