Форумы Modlabs.net: Микроконтроллеры начинающим - Форумы Modlabs.net

Перейти к содержимому

Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

Микроконтроллеры начинающим

#1 Пользователь офлайн   Day 

  • Junior
  • Pip
  • Группа: Пользователи
  • Сообщений: 14
  • Регистрация: 14 Сентябрь 06

Отправлено 24 Январь 2007 - 16:40

суть проблемы: к МК 90S2313 подключен 7ми сегментный цифровой индикатор через сдвиговый регистр 74HC164, дабы не занимать лишние лапы.
цифра выводится на индикатор следующим образом:
выставляем на CLK ноль, подаем 1 или 0 (смотря что нужно) на вход DATA,выставляем на CLK единицу
и так восемь раз.
и здесь напрашивается цикл
Так вот никак не могу додуматься как выводить цифры в цикле (на Си, компилятор CodeVision)
0

#2 Пользователь офлайн   listener 

  • Advanced Member
  • PipPipPipPipPipPipPip
  • Группа: Пользователи
  • Сообщений: 618
  • Регистрация: 08 Май 03

Отправлено 25 Январь 2007 - 03:49

Например, так:

for (i = 0; i < 8; i++) {

  CLK = 0;  

  DATA = (number&(1 << i)) ? 0 : 1;

  CLK = 1;

}


Задержки расставлять по вкусу (и возможностям регистра), теоретически, должно работать и без них.

Есть и более оптимальные варианты (сдвинуть число вправо и взять младший бит, двигать маску и т.д.)

А еще есть такая вещь, как 74HC595 - он напрямую к SPI цепляется.
0

#3 Пользователь офлайн   Day 

  • Junior
  • Pip
  • Группа: Пользователи
  • Сообщений: 14
  • Регистрация: 14 Сентябрь 06

Отправлено 25 Январь 2007 - 10:59

вот про эту строчку можно по подробнее:
DATA = (number&(1 << i)) ? 0 : 1;


что она делает, что такое "number", "? 0 : 1;"-таких конструкций еще не встречал
0

#4 Пользователь офлайн   listener 

  • Advanced Member
  • PipPipPipPipPipPipPip
  • Группа: Пользователи
  • Сообщений: 618
  • Регистрация: 08 Май 03

Отправлено 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".
0

#5 Пользователь офлайн   Day 

  • Junior
  • Pip
  • Группа: Пользователи
  • Сообщений: 14
  • Регистрация: 14 Сентябрь 06

Отправлено 26 Январь 2007 - 10:46

додумался пока только до этого
#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 Большое спасибо за ответы :D
0

#6 Пользователь офлайн   listener 

  • Advanced Member
  • PipPipPipPipPipPipPip
  • Группа: Пользователи
  • Сообщений: 618
  • Регистрация: 08 Май 03

Отправлено 28 Январь 2007 - 13:17

Day
Второй сдвиг лишний. Т.е. биты выводятся не все, а через один.
В таком виде правильнее будет так:

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
0

#7 Пользователь офлайн   Day 

  • Junior
  • Pip
  • Группа: Пользователи
  • Сообщений: 14
  • Регистрация: 14 Сентябрь 06

Отправлено 31 Январь 2007 - 10:16

выкладываю то что получилось.

#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 Приветствуются камни большие и маленькие
0

Поделиться темой:


Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 members, 1 guests, 0 anonymous users