Перевод числа в массив бит

Поклонники продукции Microchip Technology Inc тусуются тут.
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Перевод числа в массив бит

Сообщение vksam »

Всем привет!
подскажите, как из числа получить последовательность бит для пересылки в сдвиговый регистр.
С самой пересылкой проблем нет.
Но вот с переводом самого числа в последовательность бит - проблема. Ничего не приходит в голову.
Набор констант не подходит.
Нужно именно конвертировать в биты

Пишу в MikroC.
Реклама
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25291
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Перевод числа в массив бит

Сообщение КРАМ »

Физически в большинстве машин биты не адресуются.
В сдвиговые регистры КОНТРОЛЛЕРА пересылаются БАЙТЫ или СЛОВА, в зависимости от разрядности машины и потребности.
Сам сдвиговый регистр и есть АППАРАТНЫЙ преобразователь слова/байта в последовательность бит.
Таким преобразователем на борту контроллеров является ЛЮБОЙ последовательный интерфейс.
UART, SPI, IIC
Можно организовать ПРОГРАММНЫЙ последовательный вывод в любой бит порта посредством маскирования этого бита в этом порту.
Тогда используется операция СДВИГА.
Сдвиг - маска с содержимым порта - вывод в порт.
Но на самом деле выводится ЦЕЛОЕ СЛОВО ИЛИ БАЙТ.
Просто остальные биты сохраняются прежними.
Реклама
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

пример кода можно?
В регистр мне надо поместит 4.
А вообще я имел в виду регистр сдвига. В моем конкретном случае это 74HC164
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25291
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Перевод числа в массив бит

Сообщение КРАМ »

Вы постарайтесь перечитать написанное...
Код пишется под железо.
Каким образом внешний регистр соединен с МК?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Перевод числа в массив бит

Сообщение Аlex »

как из числа получить последовательность бит
Число в регистрах МК итак хранится в виде последовательности бит, читайте его побитно и будет Вам счастье.
Реклама
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Перевод числа в массив бит

Сообщение Леонид Иванович »

vksam писал(а):пример кода можно?

Код: Выделить всё

void Wr_Reg(char d)
{
  for(char i = 0; i < 8; i++)
  {
    Port_SCLK_0;                       //SCLK = 0
    if(d & 0x80) Port_SDATA_1;         //вывод данных
      else Port_SDATA_0;
    d = d << 1;                        //следующий бит
    Port_SCLK_1;                       //SCLK = 1
  }
}
Макросы управления портами Port_SCLK_0 и другие имеют вид типа

Код: Выделить всё

#define Port_SCLK_0   (PORTB &= ~SCLK)
Реклама
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Re: Перевод числа в массив бит

Сообщение blackx »

Ну или к аппаратному SPI подключить регистр, тогда вообще проблем не будет :)

К слову, если в примере от Леонид Иванович требуется биты слать "ногами вперед" (сначала мдалшие), то нужно вместо 0x80 написать просто 0x1, и сдвиг поменять на правый (>>).
Изображение only pure true norwegian blackx Изображение
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

спасибо, буду пробовать.
Про сдвиги я как-то не подумал... обошелся банальным делением.
Программированием контроллеров не занимался... вот решил первую программу написать для регулятора Никитина.
Последний раз редактировалось vksam Чт июл 25, 2013 11:30:21, всего редактировалось 1 раз.
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

Леонид Иванович писал(а):

Код: Выделить всё

void Wr_Reg(char d)
{
  for(char i = 0; i < 8; i++)
  {
    Port_SCLK_0;                       //SCLK = 0
    if(d & 0x80) Port_SDATA_1;         //вывод данных
      else Port_SDATA_0;
    d = d << 1;                        //следующий бит
    Port_SCLK_1;                       //SCLK = 1
  }
}
Макросы управления портами Port_SCLK_0 и другие имеют вид типа

Код: Выделить всё

#define Port_SCLK_0   (PORTB &= ~SCLK)
Да, такой код по элегантней будет!
Спасибо!
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

И раз уж пошел такой разговор :)
Думаю прикрутить к регулятору инфракрасный приемник. Нашел на просторах интернета вот такой код
Спойлер

Код: Выделить всё

volatile char allow=0,i=0,holdr=0b00000000,took[15],toggl=2,intru=0;
 void interrupt()//ISR when interrupt occurs
 {
     if(INTCON.INT0IF==1)
    {
     INTCON=0X0;delay_us(1000);//disable the interrupt and delay of 1000us
      for(i=0;i<13;i++)//taking input
      {
           took[i]=portb.f0;
           delay_us(1778);
      }allow=1;//allow flag to 1, indicating that we have received all data
     }
}
void main()
{
 unsigned char j;
 TRISB=0XFF;TRISC=0X0;//portb input and portc output
 portc=0;
 delay_ms(2000);//stabilize the device
 INTCON=0b10010000;//enable the interrupt int0
 INTCON2.INTEDG0=0;//for falling edge
    while(1)
    {
      while(allow==0);//when allow flag is 0 then be in this loop for ever.
      if(took[1]!=toggl)//check the T bit i.e toggle bit with previous one.
      {
        if(toggl==2)toggl=took[1];
 
                      //check the fist line of code,we assigned toggl as 2,
                      //if toggl==2 then take real T bit into it 
        j=5;
        for(i=7;i<13;i++)//convert array to variable for
                             easy comparison with command
        {
           took[i]=took[i]<<j ;
           holdr=holdr|took[i];took[i]=0;
           j--;
        }
        if(holdr==1)portc.f1=~portc.f1;//comparing
        if(holdr==2)portc.f2=~portc.f2;
        if(holdr==4)portc.f3=~portc.f3;
        if(holdr==5)portc.f4=~portc.f4;
        if(holdr==6)portc.f5=~portc.f5;
      }
      holdr=0;allow=0;
      portc.f7=1;delay_ms(200);portc.f7=0;
      INTCON=0b10010000;
      INTCON2.INTEDG0=0;
    }
} 
На сколько он работоспособен в плане логики?
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Перевод числа в массив бит

Сообщение Леонид Иванович »

Если речь о декодере RC-5, то могу предложить свой:
Спойлер

Код: Выделить всё

//----------------------------------------------------------------------------

//Декодер RC-5

//----------------------------------------------------------------------------

//Декодер использует два прерывания: внешнее от фотоприемника и
//прерывание по переполнению таймера 0.
//После того, как обнаружен стартовый бит (переход из единицы
//в ноль на входе прерывания), в обработчике внешнего прерывания
//разрешается прерывание таймера 0 и загружается интервал до первой
//выборки T_SAMPLE. В прерывании таймера 0 делаются выборки для
//каждной половинки бита. Подсчет выборок ведется в переменной SampCnt.
//Количество выборок задается константой SAMPLE_COUNT.
//Логический уровень для каждой половинки бита вычисляется по
//мажоритарному принципу. Для этого вычисляется сумма выборок
//в переменной SampVal. Если на входе обнаруживается ВЫСОКИЙ уровень,
//то к этой переменной добавляется единица, если НИЗКИЙ - вычитается.
//Значение суммы не может быть равно нулю, так как общее количество
//выборок всегда задается нечетным. По первой половине текущего бита
//принимается решение о значении принятого бита. Для проверки
//корректности кода Манчестер этот уровень сравнивается со значением
//второй половины предыдущего бита, которое сохраняется в переменной
//PreVal. Если значения совпадают, была ошибка, и прием начинается
//с начала. То же самое происходит, если очередной переход на входе
//не обнаружен через время T_SAMPLE * 2 после последней выборки
//(ошибка таймаута). Принятые биты вдвигаются в переменную Rc5Code.
//Подсчет принятых битов осуществляется в переменной BitCounter.
//Когда принято RC5_LENGTH битов, прием завершен, номер системы
//копируется в переменную SysVar, а код команды - в переменную ComVar.
//Декодер поддерживает Extended RC-5 Code, второй стартовый бит
//интерпретируется как бит F (Field). Бит F представляет собой
//инвертированный дополнительный (старший) бит кода команды,
//в результате количество команд удваивается.

//----------------------------------------------------------------------------

#include "Main.h"
#include "RC5.h"

//----------------------------- Константы: -----------------------------------

#define PRE            64 //предделитель таймера 0
#define RC5_SLOT     1778 //длительность слота RC-5, мкс
#define RC5_LENGTH     14 //количество принимаемых битов
#define SAMPLE_COUNT    3 //количество выборок (должно быть нечетным)

#define T_SAMPLE_US (RC5_SLOT / ((SAMPLE_COUNT + 1) * 2))
#define T_SAMPLE    (T_SAMPLE_US * F_CLK / PRE + 0.5)

//----------------------------- Переменные: ----------------------------------

static char SampCnt;        //счетчик выборок
static signed char SampVal; //величина, полученная суммой выборок
static bool PreVal;         //значение педыдущего полу-интервала
static int RC5Code;         //принятый код
static char BitCounter;     //счетчик принятых битов
static char SysVar;         //номер системы
static char ComVar;         //код команды

//-------------------------- Прототипы функций: ------------------------------

#pragma vector = INT0_vect
__interrupt void EdgeIR(void);   //прерывание по сигналу фотоприемника
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void);  //прерывание таймера 0

//----------------- Инициализация модуля декодера RC-5: ----------------------

void RC5_Init(void)
{
  BitCounter = RC5_LENGTH;  //инициализация счетчика битов
  PreVal = 1;               //перед стартовым битом была единица
  SysVar = 0xFF;            //неиспользуемый код системы
  ComVar = 0xFF;            //неиспользуемый код команды
  TCCR0 = (1<<CS00) | (1<<CS01); //прескалер CK/64 для таймера 0
  MCUCR = (1<<ISC01);       //INT0 по спаду
  GIFR = (1<<INTF0);        //очистка отложенных прерываний
  GICR |= (1<<INT0);        //разрешение INT0
}

//------------- Обработчик прерывания по сигналу фотоприемника: --------------

#pragma vector = INT0_vect
__interrupt void EdgeIR(void)
{
  Port_LED_1;
  GICR &= ~(1<<INT0);       //запрещение INT0
  TCNT0 = 256 - T_SAMPLE;   //интервал до первой выборки
  TIFR = (1<<TOV0);         //очистка отложенных прерываний
  TIMSK |= (1<<TOIE0);      //разрешение прерываний таймера 0
  SampCnt = SAMPLE_COUNT * 2; //общее количесто выборок
  SampVal = 0;              //очистка принятого значения
}
    
//------------------ Обработчик прерывания таймера 0: ------------------------

#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void)
{
  if(SampCnt)                       //проверка таймаута
  {
    if(Pin_RC5) SampVal++;          //если на входе единица, инкремент суммы,
      else SampVal--;               //иначе декремент суммы
      
    if(--SampCnt)                   //декремент количества выборок
    {
      if(SampCnt != SAMPLE_COUNT)
      {
        TCNT0 = 256 - T_SAMPLE;     //продолжаем опрашивать
        return;
      }
      else                          //первая половина интервала закончилась:
      {
        TCNT0 = 256 - T_SAMPLE * 2; //загрузка интервала между сериями выборок
        bool Val = (SampVal > 0);   //оценка бита
        if(Val != PreVal)           //проверка корректности кода Манчестер
        {
          RC5Code <<= 1;            //сдвиг принятого кода
          if(!Val) RC5Code |= 1;    //первая половина = 0, бит = 1
          SampVal = 0;              //очистка счетчика выборок
          return;
        }
      }
    }
    else                            //вторая половина интервала закончилась:
    {
      TCNT0 = 256 - T_SAMPLE * 2;   //загрузка интервала таймаута
      PreVal = (SampVal > 0);       //оценка второй половины бита
      if(PreVal)                    //обнаружена единица,
        MCUCR &= ~(1<<ISC00);       //INT0 по спаду,
          else MCUCR |= (1<<ISC00); //иначе INT0 по фронту
      GICR |= (1<<INT0);            //разрешение INT0
      if(--BitCounter)              //декремент счетчика битов
        return;                     //переход к приему следующего бита
      SysVar = (RC5Code >> 6) & 0x3F; //номер системы
      ComVar = RC5Code & 0x3F;      //код команды
      if(!(RC5Code & 0x1000))       //добавление бита F
        ComVar |= 0x40;
    }
  }
  BitCounter = RC5_LENGTH;          //загрузка счетчика битов
  PreVal = 1;                       //перед стартовым битом была единица
  TIMSK &= ~(1<<TOIE0);             //запрещение прерываний таймера 0
  MCUCR &= ~(1<<ISC00);             //INT0 по спаду
  GICR |= (1<<INT0);                //разрешение INT0
  Port_LED_0;
}

//------------------------- Чтение номера системы: ---------------------------

char RC5_GetSys(void)
{
  return(SysVar);
}

//-------------------------- Чтение кода команды: ----------------------------

char RC5_GetCom(void)
{
  return(ComVar);
}

//----------------------------------------------------------------------------
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

Это под AVR?
Мне бы под PIC
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Перевод числа в массив бит

Сообщение Аlex »

Мне бы под PIC
Разницы особой нет. Код будет отличаться только работой с таймером и внешним прерыванием. Перевести этот код под свой компилятор и МК проблем не составит, тем более, что код отлично прокомментирован.
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

Аlex писал(а):
Мне бы под PIC
Разницы особой нет. Код будет отличаться только работой с таймером и внешним прерыванием. Перевести этот код под свой компилятор и МК проблем не составит, тем более, что код отлично прокомментирован.
Угу. Буду пробовать "курить матчасть"
vksam
Прорезались зубы
Сообщения: 214
Зарегистрирован: Вс фев 12, 2012 20:22:53

Re: Перевод числа в массив бит

Сообщение vksam »

Дошло дело до макетной сборки.
И появился очередной глупый вопрос.
Если использую порт A для вывода в сдвиговый регистр - на выходе ничего. Не работает. Хотя протеус моделирует
Но если использовать порт В - все хорошо. На индикаторе получаю то что нужно.
В чем может быть причина?
Спойлер

Код: Выделить всё

#define RESET RA2_bit
#define Clock RA1_bit
#define DATA RA0_bit


int vl = 127;

void write_data( char val){
     unsigned short n = val;
     unsigned short i = 7;
     

    for(i = 0; i < 8; i++)
    {
      Clock = 0;                        //SCLK = 0
      if(n & 0x80) DATA = 1;         //
        else DATA = 0;
      n = n << 1;                      //
      Clock = 1;                       //SCLK = 1
    }

}

void tick(){
     Delay_ms(1);
}

void print( int val){

     short s,d;

     short segment;
     bit isNegative;

      segment = 1;
      if( val < 0){
          isNegative = 1;
      }else{
          isNegative = 0;
      }

      val = abs(val);


      RESET = 1;
      write_data(1);
      write_data(128);
      tick();
      RESET = 0;

      RESET = 1;
      write_data(2);
      write_data(128);
      tick();
      RESET = 0;

}

void main()
{

    PORTA = 0;
    PORTB = 0;

    TRISA = 0b00000000;
    TRISB = 0b00000000;

    
    DATA = 0;
    
    while(1){
             print(vl);
    }
}


Вложения
Безымянный.jpg
(63.74 КБ) 649 скачиваний
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Перевод числа в массив бит

Сообщение Аlex »

Если один порт рабтает, а другой нет, значит нужно курить даташит на предмет разницы этих портов. Благо даташиты у микрочипа отличные. А лень и метод тыка ни к чему хорошему не приведут. Нужно читать, читать и ещё раз читать....

ЗЫ: А протеус не есть инструмент для проверки правильного написания программ. Нельзя ему на столько доверять. Удостовериться в правильности есть только один способ - проверить на железе.
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Перевод числа в массив бит

Сообщение dosikus »

Ну протеус в данном случае не причем , Mid Range он нормально симулирует.
А PORTA надо сделать цифровым - отключите компараторы . Записать в CMCON 0x07 .
И как ALex верно заметил - читать , читать и читать
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25291
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Перевод числа в массив бит

Сообщение КРАМ »

ANSEL тоже нужно сбросить...
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Перевод числа в массив бит

Сообщение dosikus »

КРАМ писал(а):ANSEL тоже нужно сбросить...
Сбросит , когда он в 628'ом появится. :)))
Может в следующей реинкарнации ...
Кстати PIC16F1827 аналог 628 и стоит в 2 раза дешевле ...
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Перевод числа в массив бит

Сообщение alex_ »

Для последовательного вывода я использую следующий код:

char t;

for(i=0;i<8;i++)
{
PORTB.B0 = t.B7;
t = t<<1;
}

Он минимализирован до безобразия, отсутствуют операторы if и else, что увеличивет скорость передачи.
PS пишу на MikroC
Ответить

Вернуться в «PIC»