CodeVisionAVR+MAX7219 подскажите с программой

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 5
Зарегистрирован: Сб ноя 29, 2014 15:19:36

Сообщение Technik_91 »

Всем привет! Уже неделю не могу победить MAX7219, подключенный к Atmega8. Знаю, может все и просто, ошибки у меня ламерские, но и познания в программировании не особо большие, желание есть, а вот опыта не хватает :( По гуглу перепробовал много вариантов, ни один не заработал, подскажите что не так в моей программе. Не проходит даже инициализация макса. Вот листинг CodeVisionAVR:

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

#include <mega8.h>

#define SPI_PORTX PORTC
#define SPI_DDRX DDRC
 
#define SPI_MISO 2 
#define SPI_MOSI 5
#define SPI_SCK 4
#define SPI_SS 3
 
/*инициализация SPI модуля в режиме master*/
void SPI_Init(void)
{
   /*настройка портов ввода-вывода
   все выводы, кроме MISO выходы*/
    SPI_DDRX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
    SPI_PORTX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);

    SPI_PORTX |= (1<<SPI_SS);
    SPI_PORTX &= ~(1<<SPI_SCK);
    SPI_PORTX &= ~(1<<SPI_MOSI);

}

void SPI_WriteData(char adres, char data)
{  char i=16; 
   int tmp=adres;
   tmp = (tmp<<8)|data;   
   SPI_PORTX &= ~(1<<SPI_SS); 
  {while(i>0)
        { 
        SPI_PORTX &= ~(1<<SPI_SCK);
        SPI_PORTX.SPI_MOSI=((tmp & (1<<(i-1))) != 0 );
        SPI_PORTX |= (1<<SPI_SCK);
        i--;
        }
      
   }        
   SPI_PORTX &= ~(1<<SPI_SCK);
   SPI_PORTX |= (1<<SPI_SS);
   SPI_PORTX &= ~(1<<SPI_MOSI);
}

char count=8;

void main(void)
{

SPI_Init();

SPI_WriteData(0xF,0x0);
SPI_WriteData(0xC,0x0);
SPI_WriteData(0xB,0x7);
SPI_WriteData(0x9,0x0);
SPI_WriteData(0xA,0xF);

{while(count>0)
        { 
        SPI_WriteData(count,0x0);
        count--;
        }
}

while (1)
      {
      
      }
}


Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 281
Зарегистрирован: Пт ноя 15, 2013 20:58:23

Сообщение Halex »

Во-первых, приучитесь ПРАВИЛЬНОписанию шестнадцатиричных чисел, чтобы окружающих не коробило. А во-вторых, тем более, что начинающий, снабжать свои недельные потуги комментариями, чтобы остальным не ломать моСК над Вашим кодом. В свете этих двух замечаний приведу кусочек вашего кода так, как он должен был БЫ выглядеть в нормальном изложении, а уж что там не так - догадаетесь сами. Для того и комментарии пишутся.

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

SPI_Init();

SPI_WriteData(0x0F,0x00); // Отключить тестовый режим
SPI_WriteData(0x0C,0x00); // Выключить индикацию (!!!)
SPI_WriteData(0x0B,0x07); // Установить количество подключенных индикаторов (разрядов) - 8
SPI_WriteData(0x09,0x00); // Отключить встроенный декодер BCD для всех разрядов (!!!)
SPI_WriteData(0x0A,0x0F); // Установить максимальную яркость индикации
Вот из кода в таком виде, как говорят, даже ежу всё становится понятно, а уж нам пушистым и хвостатым и подавно.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

На самом деле 0xF тоже пишут, это не ошибка и не плохое форматирование. Такое встречается, например, в библиотеке vusb.
Но мне тоже кажется логичным дополнять двоичную запись до размера переменной.
На счет комментариев - полностью согласен, они нужны, особенно когда "программист" сам не знает что и для чего делает.
Грызет канифоль
Аватара пользователя
Сообщения: 281
Зарегистрирован: Пт ноя 15, 2013 20:58:23

Сообщение Halex »

COKPOWEHEU писал(а):На самом деле 0xF тоже пишут, это не ошибка и не плохое форматирование.
Компилятор, да и то не всякий, такое проглотит, а вот разбор чужих полетов уже затрудняется. МоСК уже приучЁн разворачивать в уме байты из шестнадцатеричной в двоичную форму. Когда глаза чего-то не находят, соответственно и моСК тормозит. Напишите в столбик одно под другим несколько байт в шестнадцатеричной форме, причем вперемешку - "детям до шестнадцати и старше" (ИМХО - часть без старшего незначащего нуля). Гарантирую, глаза сами будут выхватывать последние и тормозить на них - а не АшиПка ли?. Аналогично и с двухбайтовыми long.
COKPOWEHEU писал(а):Но мне тоже кажется логичным дополнять двоичную запись до размера переменной.
Не в обиду Вам, но повторюсь - шестнадцатеричную. В двоичной форме запись начинается с 0b и далее единичками/нулями побитно.
ПЫСЫ Я не придираюсь, просто мы так совсем топикстартера с пути истинного сбить можем. А у него и так косяк на косяке. Мало того, что при инициализации MAX-а он его просто вырубил, так еще и в майне "приколов" хватает. Первый while пролетит за микросекунды и благополучно уйдет в бесконечный пустой while(1).
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 5
Зарегистрирован: Сб ноя 29, 2014 15:19:36

Сообщение Technik_91 »

В том то и дело, что max не вырубается, как горели все индикаторы, так и горят. Указывать на мои ошибки правильно, но дельного совета так никто и не дал. :( Так в чем мои ошибки? Я поправил код, как вы сказали, спасибо. Но он как был не рабочим, так таким и остается.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Не в обиду Вам, но повторюсь - шестнадцатеричную
Двоичную, восмеричную, шестнадцатеричную. Любую, привязанную к железу.
Когда глаза чего-то не находят, соответственно и моСК тормозит.
Ну, запись в столбик аналогичных десятичных чисел проблемы не вызваает. Тут уж кому как удобнее. Неправильным форматированием это считать не стоит.
В двоичной форме запись начинается с 0b и далее единичками/нулями побитно.
Запись 0b111 вполне проглатывается компилятором и может быть удобна для задания нескольких связанных битов.
SPI_PORTX &= ~(1<<SPI_SCK);
SPI_PORTX.SPI_MOSI=((tmp & (1<<(i-1))) != 0 );
SPI_PORTX |= (1<<SPI_SCK);
А тут случайно не надо добавить задержку? Или, например, воспользоваться аппаратным модулем? И while'ы заменить на обычные for.
Реклама
Родился
Сообщения: 5
Зарегистрирован: Сб ноя 29, 2014 15:19:36

Сообщение Technik_91 »

задержки по 10мс добавил, ничего не поменялось. Аппаратным модулем тоже пробовал, не заработало, а когда пошагово в авр студии выпонял программу, то у PORTC никакие биты не менялись, в отличие от своего варианта. По этому на нем и остановился. А насчет задержек - max вроде до 10 Мгц работает, а мега на 8. Должно же работать...
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Аппаратным модулем тоже пробовал, не заработало, а когда пошагово в авр студии выпонял программу, то у PORTC никакие биты не менялись, в отличие от своего варианта
Пробовали аппаратным модулем, выведенным на PB2-PB5 управлять устройством, висящим на PORTC?
void SPI_WriteData(char adres, char data)
Не проверяли в протеусе работу самой функции?
Я поправил код, как вы сказали
Хорошо бы его увидеть. И схему заодно, а лучше модель в протеусе, благо там все это есть.
Родился
Сообщения: 5
Зарегистрирован: Сб ноя 29, 2014 15:19:36

Сообщение Technik_91 »

Когда подключал к аппаратному модулю - подключал к аппаратным выводам SPI. Тему можно закрывать, я разобрался. Как тут справедливо заметили, надо было посмотреть как я конфигурирую MAX.

SPI_WriteData(0x0C,0x00); // Выключить индикацию (!!!) - отключает индикацию, просто я инициализацию с сайта посмотрел, и был уверен что она правильная. А стоило посмотреть в даташит. А горели все сегменты потому что у меня семисегментник с общим анодом, соответственно когда микросхема ничего не выводила - выводы были притянуты к земле - все сегменты горели. Спасибо что помогли :beer:
Грызет канифоль
Аватара пользователя
Сообщения: 281
Зарегистрирован: Пт ноя 15, 2013 20:58:23

Сообщение Halex »

Technik_91 писал(а): А горели все сегменты потому что у меня семисегментник с общим анодом
"Лечится" и такое. К выводам сегментов MAX-a подключаются общие аноды индикатора, а к выводам разрядов MAX-а - сегменты индикатора. Вот тогда действительно внутренний дешифратор надо обязательно отключить, а данные перед выводом транспонировать.
Родился
Сообщения: 5
Зарегистрирован: Сб ноя 29, 2014 15:19:36

Сообщение Technik_91 »

Так и сделал. Спасибо за подсказки. Все работает, только не удобно, все таки с общим катодом было бы удобнее :)
Родился
Сообщения: 2
Зарегистрирован: Ср ноя 18, 2015 08:19:13

Сообщение Romul »

Программа то кстати рабочая. Единственная оплошность при инициализации. Вместо

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

SPI_WriteData(0x0C,0x00); // Выключить индикацию 
нужно писать

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

SPI_WriteData(0x0C,0x01); // Включить индикацию 
А если еще включить декодер

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

SPI_WriteData(0x09,0xFF); // Включить встроенный декодер BCD для всех разрядов (!!!)
то информация на индикаторе будет отображаться в явном виде. То есть передали

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

SPI_WriteData(0x01,0x01); 
значит в первом разряде единица и отобразится. И таблицу перекодировки писать не нужно. В качестве примера эта же, но уже рабочая программа для тестирования китайского восьмиразрядного индикатора.

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

#include <mega2560.h>
#include <delay.h> 

#define SPI_PORTX PORTB
#define SPI_DDRX DDRB
 
#define SPI_MISO 4 
#define SPI_MOSI 7
#define SPI_SCK 5
#define SPI_SS 6



unsigned char count = 0;

unsigned int dig = 0;





 
/*инициализация SPI модуля в режиме master*/
void SPI_Init(void)
{
   /*настройка портов ввода-вывода
   все выводы, кроме MISO выходы*/
    SPI_DDRX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
    SPI_PORTX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);

    SPI_PORTX |= (1<<SPI_SS);
    SPI_PORTX &= ~(1<<SPI_SCK);
    SPI_PORTX &= ~(1<<SPI_MOSI);

}

void SPI_WriteData(char adres, char data)
{ 
   char i=16; 
   int tmp=adres;
   tmp = (tmp<<8)|data;   
   SPI_PORTX &= ~(1<<SPI_SS); 
   
     
  {while(i>0)
        { 
         
        PORTB &= ~(1<<SPI_SCK);
        PORTB =(((tmp & (1<<(i-1))) != 0 )<<SPI_MOSI);            
        PORTB |= (1<<SPI_SCK); 
          i--;
        }

   }        
   
   PORTB &= ~(1<<SPI_SCK); 
   PORTB |= (1<<SPI_SS);   
   PORTB &= ~(1<<SPI_MOSI);  
   
 
}


 void ind(unsigned int c )
{

 SPI_WriteData(0B00000001, c% 10);
 SPI_WriteData(0B00000010, c% 100 / 10);       
 SPI_WriteData(0B00000011, c% 1000 / 100);       
 SPI_WriteData(0B00000100, c% 10000 / 1000);    
 SPI_WriteData(0B00000101, c% 100000 / 10000);
 SPI_WriteData(0B00000110,0B00000000);           // c% 1000000 / 100000);      
 SPI_WriteData(0B00000111,0B00000000);           // c% 10000000 / 1000000);
 SPI_WriteData(0B00001000,0B00000000);           // c% 100000000 / 10000000);
}





void main(void)
{

SPI_Init();

 delay_us(1000); 
SPI_WriteData(0b00001111,0b00000000);     // Тест дисплея
 delay_us(1000); 
SPI_WriteData(0b00001011,0b00000111);    //  Кол-во символов 
 delay_us(1000);
SPI_WriteData(0b00001001,0b11111111);     //  Дешифраторы включены для всех разрядов
 delay_us(1000);  
SPI_WriteData(0b00001010,0b00000011);     // Интенсивность свечения средняя
 delay_us(1000);
SPI_WriteData(0b00001100,0b00000001);    // Выход из сна
 delay_us(1000);


while (1)
      {  
  if (count++>100) count=0,dig++;
  if (dig>64000) dig=0;     
        
  
  ind(dig); 

      

 
      
      }
}
Ответить

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