Научите писать программы для МК

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1573
Зарегистрирован: Сб окт 09, 2010 12:33:48
Откуда: Незалежная

Сообщение К@Т »

Вот неплохие самоучители по пикам http://www.labkit.ru/html/Assembler_for_PIC....
...http://www.labkit.ru/html/C_for_PIC
ИМХО лучше учитса на пиках,т.к. их легче понять,да и фьюзофренией пики не болеют в отличие от авр.
У кошки 4 ноги и хвост-плюс,минус,вход,выход,а хвост-земля.....Надо переходить с китайской бурды на канифоль.......[url=http://infobar.hsdn.org/][img]http://static.hsdn.org/infobar/350x60.gif[/img][/url]
Реклама
Встал на лапы
Сообщения: 135
Зарегистрирован: Чт окт 25, 2007 11:00:10
Откуда: Russland

Сообщение krant »

Правильно, учится надо надо на пиках. Да и тем более Микрочип себя чуствует намного лучше нежели АВР.

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

Вот путь которы я Вам советую:
Шпак Ю.А.

эта книга можно сказать основа основ в Си програмировании, учитывающая специфику програмирования для контроллеров. Там подробно изложена структура языка, с пояснением всего и вся.

Если Вы продолжите изучать пик контроллеры, то следующими книгами у вас должны быть:

Барри Брэй
Лусио Ди Джасио.

Лучше не пожалеть денег, а покупать книги в бумажном варианте, а не в электронном. Книги очень толковые, всё хорошо расписано (Правда по Брэю экран у меня работать не стал, но это единственный его косяк с которым я столкнулся).

Я советую кстати учиться не на живом общении, а на чтении исходников, это более действенный вариант :beer:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

доброго времени суток многоуважаемые знатоки, для меня тоже очень актуальна данная тема т.к. сам толком не знаю с чего начать и как закончить написание проги............., есть опыт :)) при написании проги которая мигает светодиодами.........., пишу на Си в CodeVision..............., на данный момент поставил перед собой цель написать прогу для часов на atmega8............., в качестве индикаторов ИН-4.................., что должно составлять костяк проги, какова должна быть ее структура.........., подскажите плиз :))
Tell Me The Truth
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 330
Зарегистрирован: Чт июн 23, 2011 07:55:51

Сообщение korsaj »

Костяк программы - часы (прерывания от таймера). В прерываниях (допустим каждые 50мс) подсчитываешь время (вначале милисикунды, до переполнения, далее секунды, далее единицы минут, далее десятки минут, до 6, далее единицы часов, далее десятки часов до 2 ), опрашиваешь кнопки и сравниваешь текущее время с будильником. В основном цикле можно ничего не размещать, а можно разместить будильник и опрос кнопок (не забываем о дребезге контактов).

ЗЫ Удачи!
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

это единственно возможное решение данной задачи ?
Tell Me The Truth
Реклама
BVS
Потрогал лапой паяльник
Сообщения: 336
Зарегистрирован: Пн май 23, 2011 18:27:41

Сообщение BVS »

FreshMan писал(а):это единственно возможное решение данной задачи ?
Ну, решений может быть столько, сколько людей будет это делать.
Но не надо сразу идти своим путем, возьмите чужой проект, можно и не один, разберитесь в нем попробуйте изменить его, не бойтесь экспериментов.
Пока у вас одни вопросы и нет действий, все ответы есть в Интернете (Книги, даташиты, статьи)
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 382
Зарегистрирован: Сб фев 18, 2012 14:50:22

Сообщение mazda »

HeLiO писал(а):полнаый бред. только запуешься если начинать с ассемблера. НУжно начинать на СИ писать и потом использовать только си, а ассемблер начать гораздо позже, и то достаточно на уровне понимания кода, самому писать вряд ли понадобится что либо
ой неправ, как неправ. это от мозга конкретного человека зависит, мы с товарищами с асма начинали и с основных процессов внутри процессора и работали с эмуляторами где пишешь хекс код и видишь из какого регистра в какой что идёт, и потом си пристроить к этому делу легко.
тем более на асме можно делать то чего нельзя на си, компилятор некоторые вещи не оптимизирует, бывают довольно оригинальные вычисления вобщето.
Главное научиться читать и писать, а там приложиться
я его в гугл на дрц прогнал, вы знаете, пи-када нет.
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

А я ведь тоже с ассемблера начинал, когда АВРки изучал. Но на Си так и не перешёл. За то, когда перешёл на ядра Cortex M3 \ A8, так там сразу с Си начал, ибо ассемблер там жуткий.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

написал свою первую прогудля часов, но она почему-то не работает..........., подскажите пожалуйста в чем может быть причина ? :dont_know:
в ней выводятся только секунды и минуты на индикаторы ИН-4, аноды этих индикаторов подключены к 4 старшим разрядам порта D, а катоди к 155ид1, информационные входы которой подключены к 4 младшим разрядам порта D.

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

#include <mega8.h>
#include <delay.h>

#define kn_sec_reset PINC.0  // на 0 пин порта С подключена кнопка сброса секунд
#define kn_min_up PINC.1    //  на 1 пин порта С подключена кнопка инкремента минут

unsigned char sec, min, x, i;
unsigned char number[4];               // в этом массиве мы будем хранить десятки и единици секунд и минут
unsigned char znak[4]={16,32,64,128};  // в этом массиве мы храним номер анода индикатора определенного разряда              



interrupt [TIM1_COMPA] void timer1_compa_isr(void)   // Timer1 срабатывает каждые 5мс
{
if (++x==200) {sec++; x=0;};
}

void output(unsigned char sec, unsigned char min)
{
number[0]=sec%10;  //в массив записываем остаток от деления преременной sec
number[1]=sec/10; // в массив записываем целую часть от деления преременной sec 
number[2]=min%10; // в массив записываем остаток от деления преременной min
number[3]=min/10; // в массив записываем целую часть от деления преременной min

for (i=0;i!=4;i++)  // по очереди выводим на индикаторы выше вычесленные данные
 {
  PORTD=0;
  PORTD=(number[i]|znak[i]);
 };
 
}


void main(void)
{
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P 
PORTC=0x03;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// Global enable interrupts
#asm("sei")

while (1)
      {
       
       output(min,sec);
       if (sec==60) {sec=0; min++;};
       if (min==60) min=0;
       if (kn_sec_reset==0) {delay_ms(10);sec=0; while(kn_sec_reset==0){}; delay_ms(10);};
       if (kn_min_up==0) {delay_ms(10);min++; while(kn_min_up==0){}; delay_ms(10);};

      };
}
Tell Me The Truth
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Сообщение SII »

DX168B писал(а):А я ведь тоже с ассемблера начинал, когда АВРки изучал. Но на Си так и не перешёл. За то, когда перешёл на ядра Cortex M3 \ A8, так там сразу с Си начал, ибо ассемблер там жуткий.
Ну, насчёт армовского ассемблера Вы неправы: он много удобней и мощнее, чем у AVR.

Изучать лучше, ИМХО, сначала Паскаль/Дельфи на ПК (написание консольных приложений), и лишь затем начинать работать с МК. Главное в программировании -- алгоритмистика, а отнюдь не конкретный язык программирования, и настоящим программистом делает не знание одного или нескольких языков, а умение превращать задачу в чёткий алгоритм её решения. Ну а на при работе с МК знание ассемблера абсолютно обязательно: есть масса вещей, которые ни на каком языке высокого уровня не сделаешь вообще или же сделаешь, но неэффективно. И если на ПК от таких вещей программиста-прикладника спасает ОС (не приходится напрямую работать с железом, обрабатывать прерывания и т.п.), то на МК всё надо делать самому.
Мучитель микросхем
Сообщения: 478
Зарегистрирован: Ср окт 15, 2008 09:33:03
Откуда: Воронеж

Сообщение Galizin »

FreshMan писал(а):

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

for (i=0;i!=4;i++)  // по очереди выводим на индикаторы выше вычесленные данные
 {
  PORTD=0;
  PORTD=(number[i]|znak[i]);
 };
}
В комментарии написано, что выводите по очереди, а на самом деле очень быстро меняете числа. Настолько быстро (несколько микросекунд), что индикатор не успевает отобразить ничего кроме одной цифры. На нее тратится гораздо больше времени, потому что программе нужно выйти из функции, попасть в главный цикл, а потом снова вернуться. Нужно каким то образом сделать так, что бы показания изменялись равномерно во времени и помедленнее, например раз в 5мс. Для этого можно например убрать цикл и менять состояние порта только один раз во время вызова функции с соотв наращиванием счетчика, а в функции делать смену только если будет выставлен флаг в прерывании. Или перенести вывод в прерывание.
Это можно сравнить с объявлениями на столбе. Если Вы хотите что бы увидели все 4 объявления, то должны будете их менять например с интервалов в один час. Если же Вы наклеете сразу все четыре друг на друга, то шанса увидеть нижние под последним нет.
Грызет канифоль
Аватара пользователя
Сообщения: 260
Зарегистрирован: Чт янв 13, 2011 18:54:29
Откуда: Минск

Сообщение ds1307 »

FreshMan писал(а):
for (i=0;i!=4;i++) // по очереди выводим на индикаторы выше вычесленные данные
Мне кажется надо for (i=0;i<4;i++)
Более глубоко не вникал
Учиться, учиться, ...
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

вот что получилось опосля переделки:

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

#include <mega8.h>
#include <delay.h>

#define kn_sec_reset PINC.0  // на 0 пин порта С подключена кнопка сброса секунд
#define kn_min_up PINC.1    //  на 1 пин порта С подключена кнопка инкремента минут

unsigned int x;
unsigned char sec, min,i;
unsigned char number[4];               // в этом массиве мы будем хранить десятки и единици секунд и минут
unsigned char znak[4]={16,32,64,128};  // в этом массиве мы храним номер анода индикатора определенного разряда              



interrupt [TIM0_OVF] void timer0_ovf_isr(void)// Timer 0 срабатывает каждую мс
{
// Reinitialize Timer 0 value
TCNT0=0x83;
// Place your code here
if(++x==1000) {sec++; x=0;};
}


interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Timer 1 срабатывает каждые 5мс
{
PORTD=0;
switch (i) 
    {
    case 0:PORTD=number[i]|znak[i];break;
    case 1:PORTD=number[i]|znak[i];break;
    case 2:PORTD=number[i]|znak[i];break;
    case 3:PORTD=number[i]|znak[i];break;
    }; 
  if (++i==4)i=0;
}



void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P 
PORTC=0x03;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x02;
TCNT0=0x83;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x11;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
       number[0]=sec%10;  //в массив записываем остаток от деления преременной sec
       number[1]=sec/10; // в массив записываем целую часть от деления преременной sec 
       number[2]=min%10; // в массив записываем остаток от деления преременной min
       number[3]=min/10; // в массив записываем целую часть от деления преременной min
       if (sec==60) {sec=0; min++;};
       if (min==60) min=0;
       if (kn_sec_reset==0) {delay_ms(10);sec=0; while(kn_sec_reset==0){}; delay_ms(10);};
       if (kn_min_up==0) {delay_ms(10);min++; while(kn_min_up==0){}; delay_ms(10);};

      };
}

какие будут предложения в плане модернизации и усовершенствования ? :tea:
Tell Me The Truth
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

немного модернезировал прогу но она перестала работать..............., вроде все так, но они стали идти ОЧЕНЬ медленно..........., подскажите, плиз, где я ошибся ? :dont_know:

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

#include <mega8.h>
#include <delay.h>

#define kn_sec_reset PINC.0  // на 0 пин порта С подключена кнопка сброса секунд
#define kn_min_up PINC.1    //  на 1 пин порта С подключена кнопка инкремента минут

#define anod_sec_l (PORTD|=(1<<4))
#define anod_sec_h (PORTD|=(1<<5))
#define anod_min_l (PORTD|=(1<<6))
#define anod_min_h (PORTD|=(1<<7))

unsigned int var;
unsigned char sec, min,i;
unsigned char number[4];               // в этом массиве мы будем хранить десятки и единици секунд и минут
//unsigned char znak[4]={16,32,64,128};  // в этом массиве мы храним номер анода индикатора определенного разряда              



interrupt [TIM0_OVF] void timer0_ovf_isr(void)// Timer 0 срабатывает каждую мс
{
// Reinitialize Timer 0 value
TCNT0=0x83;
// Place your code here
if(++var==1000) {sec++; var=0;};
}


interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Timer 1 срабатывает каждые 5мс
{
PORTD=0;
switch (i) 
    {
    case 0:PORTD=number[i]; anod_sec_l; break;
    case 1:PORTD=number[i]; anod_sec_h; break;
    case 2:PORTD=number[i]; anod_min_l; break;
    case 3:PORTD=number[i]; anod_min_h; break;
    }; 
  if (++i==4)i=0;
}


void mathematics(unsigned char sec, min)
{
number[0]=sec%10;  //в массив записываем остаток от деления преременной sec
number[1]=sec/10; // в массив записываем целую часть от деления преременной sec 
number[2]=min%10; // в массив записываем остаток от деления преременной min
number[3]=min/10; // в массив записываем целую часть от деления преременной min
}


void main(void)
{
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P 
PORTC=0x03;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x02;
TCNT0=0x83;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x11;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
       mathematics (min,sec);
       if (sec==60) {sec=0; min++;};
       if (min==60) min=0;
       if (kn_sec_reset==0) {delay_ms(10);sec=0; while(kn_sec_reset==0){}; delay_ms(10);};
       if (kn_min_up==0) {delay_ms(10);min++; while(kn_min_up==0){}; delay_ms(10);};
      };
}
Tell Me The Truth
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

неуж то никто не знает :)
Tell Me The Truth
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

в место прерывания по переполнению

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

interrupt [TIM0_OVF] void timer0_ovf_isr(void)// Timer 0 срабатывает каждую мс
{
// Reinitialize Timer 0 value
TCNT0=0x83;
// Place your code here
if(++var==1000) {sec++; var=0;};
}
используйте прерывание по компаратору с автоматическим сбросом регистра TCNT0 бит WGM01

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

 interrupt [TIM0_COMPA] void timer1_compa_isr(void)   // Timer1 срабатывает каждые 5мс
{
if (++x==200) {sec++; x=0;};
}

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

  TCNT0  = 0;                               
 OCR0 = ваше значение
  TCCR0  = (0<< FOC0)|(0<<WGM00)|           // разрешить работу и прерывание  таймер0
           (0<<COM01)|(0<<COM00)|
           (1<<WGM01)|(1<< CS02)|
           (0<< CS01)|(1<< CS00);
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

FreshMan, всё замечательно, но или ты вложишь тексты во вложения, или придётся их снести. Смотри сам.
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

ploop, оформить их отдельным файлом ?
Tell Me The Truth
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

phanis писал(а):используйте прерывание по компаратору с автоматическим сбросом регистра TCNT0 бит WGM01
а почему нужно делать так ? из каких соображений ? :write:
Tell Me The Truth
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Так у вас будут четкие интервалы времени по сравнению с прерыванием по переполнению. Т.е сам интервал времени между прерываниями будет реализован на аппаратном уровне.
Посмотрите на полученный ассемблер из си кода. Или просто в протеусе по экспериментируйте.
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»