Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Изменение текста программы при смене компилятора и чипа
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2, 3, 4, 5, 6, 7
sigmaN
Цитата
не меняются, а дата без разницы какая.
Прикольно. Чё и первого января и второго... ему пофиг на дату biggrin.gif

Ну а теперь серьёзно.
Подумайте как Вам нужно использовать STB в своей программе?
Вот просто человеческими словами сформулируйте алгоритм вывода положения антенны на светодиодное круговое табло это.

И в процессе вам станет понятно что делать с STB и какой там импульс: нулевой или не нулевой ))
RW6MKA
Во второй регистр в нужный бит заталкиваем 0 а востальные 1,а в первый регистр наоборот, в нужный бит 1 а в остальные 0 и устанавливаем strobe в 1, тем самым разрешая индикацию. После strobe возвращаем в 0, что никак не сказывается на индикации(Q1 - no change). Вроде бы так.
RW6MKA
Ну вообщем с регистрами я более-менее разобрался и дело вообщем не в них(хотя на всякий случай подогнал длительность импульсов CLK=1/2 DATA, а STB=DATA), поскольку вставляя вместо TH и TCNT0 реальные цифры всё работает без проблем. Я поменял возвращаемое значение Analog() на 16 битное значение и поменял способ чтения старшего байта и младшего. Всё работает нормально, но на всякий случай проверте код может чё свежим глазом углядите)))
CODE

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CD4094_PORT PORTB
#define CD4094_DDR DDRB
#define CD4094_PIN_DATA 3
#define CD4094_PIN_CLK 2
#define CD4094_PIN_STB 4
#define OnBit(address,bit) (address|=(1<<bit))
#define OffBit(address,bit) (address&=~(1<<bit))

//объявление прототипов функций
void CD4094_init(void);
void CD4094_CLK(void);
void CD4094_STB(void);
void Shift_Reg(void);
void Shift_One_Byte(uint16_t tik);
uint16_t Analog(void);

//определение переменных
volatile uint8_t TH;
uint8_t Led[2];


void main(void){

CD4094_DDR = 0x1C;//конфигурируем пины 2,3,4 на выход
CD4094_PORT = 0x00;//на входах выкл подтягивающие резисторы,на выходах уровень 0

//инициализация таймера0
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

//инициализация аналогового компаратора
ACSR=0x00;

sei();
CD4094_init();
while(1){
Led[0]=(Analog()<<8)>>8; //запись TCNT0 в первый элемент массива
Led[1]=(Analog()>>8); //запись TH во второй элемент массива
Shift_Reg();
_delay_ms(10000);
}
}



void CD4094_init(void){ //инициализация регистров
uint16_t i;
for(i=0;i<16;i++){OffBit(CD4094_PORT,CD4094_PIN_DATA) ; CD4094_CLK(); }
}

void CD4094_CLK(void){ //дёргаем ногу clk для проталкивания битов по регистру
OnBit(CD4094_PORT,CD4094_PIN_CLK);
_delay_us(10);
OffBit(CD4094_PORT,CD4094_PIN_CLK);

}

void CD4094_STB(void){ //дёргаем ногу stb для поджига светодиодов
OnBit(CD4094_PORT,CD4094_PIN_STB);
_delay_us(10);
OffBit(CD4094_PORT,CD4094_PIN_STB);

}

void Shift_Reg(void){ //загрузка сдвигового регистра
Shift_One_Byte(Led[1]);//загрузка старшего байта TH в регистр
Shift_One_Byte(Led[0]);//загрузка младшего байта TCNT0 в регистр
CD4094_STB(); //зажигаем светодиоды
}

void Shift_One_Byte(uint16_t r){ //загрузка одного байта
uint16_t i=8;
while(i--){
if(r&0x80){OnBit(CD4094_PORT,CD4094_PIN_DATA);}
else{OffBit(CD4094_PORT,CD4094_PIN_DATA);}
r<<=1;
CD4094_CLK();
}
}

uint16_t Analog(void){ //используем аналоговый компаратор для замера времени заряда кондёра
OffBit(DDRB,0); //переводим 0 выход порта В в третье состояние
TCNT0=0; //очистим счётчик-накопитель
TH=0;
TCCR0B=2; //включаем таймер0 с пределителем CLK/8
OnBit(DDRB,7); //включить транзистор
while(!(ACSR&(1<<ACO))); //ждём изменения состояния бита АСО на выходе компаратора
TCCR0B=0; //выключаем таймер
OffBit(DDRB,7); //выключаем транзистор
OnBit(DDRB,0); //разряжаем кондёр
_delay_ms(2); //время для разряда кондёра
return(TH<<8|TCNT0); //возвращаем результат замера времени
}

ISR(TIMER0_OVF_vect){ //обработка прерывания таймера0 по переполнению
//при переполнении 8-битного счётчика таймера увеличивать байт ТН на 1
TH++;
}

sigmaN
Цитата
Я поменял возвращаемое значение Analog() на 16 битное
ну надо же!! )) кажется оно там всегда таким и было.об этом мы уже рассуждали страницы четыре назад.
Цитата
и поменял способ чтения старшего байта и младшего.
вот это?
Код
Led[0]=(Analog()<<8)>>8; //запись TCNT0 в первый элемент массива
не думаю, что это хорошая идея.
Может вот так будет красивее?
Код
Led[0]= Analog() & 0xff; //запись TCNT0 в первый элемент массива


Цитата
поскольку вставляя вместо TH и TCNT0 реальные цифры всё работает без проблем
а таймер всё никак не тикает? ))
RW6MKA
Цитата
ну надо же!! )) кажется оно там всегда таким и было.об этом мы уже рассуждали страницы четыре назад.

Да нет, не всегда. В предыдущей версии кодау меня было:
Код
..........
sei();
   CD4094_init();
   while(1){
      Led[0]=Analog();
............

uint16_t Analog(void){     //используем аналоговый компаратор для замера времени заряда кондёра
   OffBit(DDRB,0);              //переводим 0 выход порта В в третье состояние
   TCNT0=0;               //очистим счётчик-накопитель
   TH=0;
   TCCR0B=2;               //включаем таймер0 с пределителем CLK/8
   OnBit(DDRB,7);         //включить транзистор
   while(!(ACSR&(1<<ACO))); //ждём изменения состояния бита АСО на выходе компаратора
   TCCR0B=0;               //выключаем таймер
   OffBit(DDRB,7);        //выключаем транзистор
   OnBit(DDRB,0);              //разряжаем кондёр
   _delay_ms(2);           //время для разряда кондёра
  Led[1]=TH;
   return(TCNT0); //возвращаем результат замера времени
}


Цитата
Led[0]=(Analog()<<8)>>8; //запись TCNT0 в первый элемент массива
не думаю, что это хорошая идея.
Может вот так будет красивее?
Код
Led[0]= Analog() & 0xff; //запись TCNT0 в первый элемент массива

Конечно красивее и правильнее, но вот я не додумался ((( crying.gif
Цитата
а таймер всё никак не тикает? ))


Он и раньше тикал, но вот тот прежний способ записи Led[] был явно не правильным.
sigmaN
Цитата
Да нет, не всегда. В предыдущей версии кодау меня было:
Даа... это совсем не весело ))
RW6MKA
Вот нужен совет по дальнейшему алгоритму действий. Таблица тиков(50 замеров по всему диапазону переменного сопротивления) у меня почти готова и дальше я диапазоны тиков( к примеру при 1 положении сопротивления было 00010111(23) при 2 положении 00011100(56) при 3 00100001(132),я беру 1 положение от 0 до 39 тиков, 2 положение 40-94 тиков.....)соотношу с 16 битным кодом определённых светодиодов.Ну а дальше проверка возвращаемого значения,выбор из массива нужного кода светодиода и загрузка его в регистр.50 замеров сделал из расчёта что первый и последний замер пойдёт на функцию остановки вращения(концевой выключатель).Как вам такой алгоритм?
sigmaN
50 замеров....как по мне - это как-то многовато.. тем более для такой приблизительно точной железяки...
Покурите ка вот... http://easyelectronics.ru/avr-uchebnyj-kur...oksimaciya.html может наведет на какие-то мысли...
Но можно канеш и по таблице втупую сделать - работать тоже будет.
RW6MKA
Т.е. вы предлагаете по полученным данным построить график зависимости напряжение - тики - светодиоды и сделать функцию которая будет всё это описывать?Хм...Надо попробовать(придётся вспомнить математику))).
RW6MKA
Опа. Дошел до измерения напряжения при котором тики переполняют счетчик и должна пойти 1 в ТН но...Видимо не работает обработчик прерываний по переполнению. Вроде глобальные прерывания разрешены? wacko.gif
sigmaN
Я уже говорил, что таймер конфигурировать надо. А у Вас почему-то одни нули в регистрах + нежелание изучать даташит... конечно так никаких прерываний и не будет )
RW6MKA
О, пардон. blush.gif Опять даташит на русском сыграл злую шутку. mad.gif Нет там описания регистра TIMSK и в частности бита TOIE0.
sigmaN
Забудьте о русских даташитах.
Это вам здесь любой скажет. Забудьте!
Сидите и со словарем и гуглем вкуривайте оригинальные доки по три часа в день(минимум) и потом вы будете щелкать их как семечки.


Русские даташиты даже хуже, чем безалкогольное пиво! Которое, как известно, ведет сами знаете куда ))))
RW6MKA
Чёт я впал в затуп.Не могу никак обмыслить как применить линейную зависимость между напряжением на входе от датчика и количеством тиков таймера.И как это всё завязать на светодиоды. wacko.gif Прочитал статью по ссылке,но не мыслю как это применимо к моему случаю? Можно конечно всё это через лесенку if-else сделать, но больно громозко получается. Что посоветуете?
sigmaN
посоветую для начала снять характеристику и построить график типа поворот ручки резистора на угол = столько-то тиков таймера. И так по всему диапазону замеров 10 - 20. Потом в Excel строим график и нагладно наблюдаем с чем нам предстоит работать и на сколько там всё линейно или не линейно(зависит кстати ещё от типа выбранного переменного резистора)... Ну а уж если там всё линейно - тогда очень просто. Уравнение прямой в той статье даётся sm.gif дальше дело за малым - коэффициент угадать и готово )
RW6MKA
Ну вот это
Цитата
поворот ручки резистора на угол = столько-то тиков таймера
то же самое что и
Цитата
напряжением на входе от датчика и количеством тиков таймера
при условии конечно что переменник имеет линейную характеристику.Формула описывающая эту прямую t=UxK,где t-тики,U-напряжение в В,К-коэффициент судя по графику равный 58.Т.е. делаем массив с 50 кодами светодиодов.Потом берём номер элемента в этом массиве равный количеству тиков/58?Я правильно понимаю?
sigmaN
смысл как раз в том, чтобы не делать массив
RW6MKA
Вот что у меня получилось
CODE

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CD4094_PORT PORTB
#define CD4094_DDR DDRB
#define CD4094_PIN_DATA 3
#define CD4094_PIN_CLK 2
#define CD4094_PIN_STB 4
#define OnBit(address,bit) (address|=(1<<bit))
#define OffBit(address,bit) (address&=~(1<<bit))

//объявление прототипов функций
void CD4094_init(void);
void CD4094_CLK(void);
void CD4094_STB(void);
void Shift_Reg(void);
void Shift_One_Byte(uint8_t r);
uint16_t Analog(void);
void Led_Pos(void);

//определение переменных
volatile uint8_t TH;
uint8_t Led[2];

void main(void){

// инициализация порта D и B
PORTD=0x70; //установка битов порта D в 0 или 1
DDRD=0x06; //установка порта D на in или out
DDRB=0x1C; //установка stb,data,clk на выход,уровень 0


//инициализация прерываний по переполнению таймера0
TIMSK=0x2;

//инициализация аналогового компаратора
ACSR=0x00;

sei();
CD4094_init();


while(1){

if ((PIND6==0)|(Analog()>23)){ //если кнопка S0(см.схему) нажата и вращение в эту сторону не дошло до конца
OnBit(PORTD,2); //включить поворот (RUN)
OffBit(PORTD,1); //реверс не включать
Led_Pos();
Shift_Reg();
}
if ((PIND4==0)|(Analog()<270)){ //если кнопка S2 нажата и вращение в эту сторону не дошло до конца
OnBit(PORTD,2); //включить поворот
OnBit(PORTD,1); //включить реверс(REV)
Led_Pos();
Shift_Reg();
}
}
}


void Led_Pos(void){ //перевод тиков в код светодиода и группы
uint16_t n;
uint8_t m;
n=Analog(); //получаем тики
m=(n-18)/4.82; //переводим тики в номер положения переменника
Led[0]=1<<((m-1)>>(8*(m>>3))); //переводим номер положения переменника в номер светодиода в группе
Led[1]=~(1<<m/8); //переводим номер положения переменника в номер группы с инверсией битов
}


void CD4094_init(void){ //инициализация регистров
uint16_t i;
for(i=0;i<16;i++){OffBit(CD4094_PORT,CD4094_PIN_DATA) ; CD4094_CLK(); }
}

void CD4094_CLK(void){ //дёргаем ногу clk для проталкивания битов по регистру
OnBit(CD4094_PORT,CD4094_PIN_CLK);
_delay_us(15);
OffBit(CD4094_PORT,CD4094_PIN_CLK);

}

void CD4094_STB(void){ //дёргаем ногу stb для поджига светодиодов
OnBit(CD4094_PORT,CD4094_PIN_STB);
_delay_us(10);
OffBit(CD4094_PORT,CD4094_PIN_STB);

}

void Shift_Reg(void){ //загрузка сдвигового регистра
Shift_One_Byte(Led[1]);//загрузка кода группы в регистр
Shift_One_Byte(Led[0]);//загрузка кода светодиода в группе регистр
OffBit(CD4094_PORT,CD4094_PIN_DATA);
CD4094_STB(); //зажигаем светодиоды
}

void Shift_One_Byte(uint8_t r){ //загрузка одного байта
uint8_t i=8;
while(i--){
if(r&0x80) OnBit(CD4094_PORT,CD4094_PIN_DATA);
else OffBit(CD4094_PORT,CD4094_PIN_DATA);
CD4094_CLK();
r<<=1;
}
}

uint16_t Analog(void){ //используем аналоговый компаратор для замера времени заряда кондёра
OffBit(DDRB,0); //переводим 0 выход порта В в третье состояние
TCNT0=0; //очистим счётчик-накопитель
TH=0;
TCCR0B=2; //включаем таймер0 с пределителем CLK/8
OnBit(DDRB,7); //включить транзистор
while(!(ACSR&(1<<ACO))); //ждём изменения состояния бита АСО на выходе компаратора
TCCR0B=0; //выключаем таймер
OffBit(DDRB,7); //выключаем транзистор
OnBit(DDRB,0); //разряжаем кондёр
_delay_ms(2); //время для разряда кондёра
return(TH<<8|TCNT0); //возвращаем результат замера времени
}

ISR(TIMER0_OVF_vect){ //обработка прерывания таймера0 по переполнению
//при переполнении 8-битного счётчика таймера увеличивать байт ТН на 1
TH++;
}



но компилятор ругается,а я не пойму почему.
Цитата
Loaded plugin Proteus VSM Viewer
Loaded plugin STK500
gcc plug-in: No WinAVR installation found. Using AVR Toolchain instead if installed. The AVR GCC plug-in can still be used if you set up your own build tools.
gcc plug-in: Failed to get "WinAVR" directory from registry.
gcc plug-in: PlugInUtility::setupAndCheckWinAVR() Found avr-gcc at C:\Program Files\Atmel\AVR Tools\AVR Toolchain\bin\avr-gcc.exe
gcc plug-in: PlugInUtility::setupAndCheckWinAVR() Found make at C:\Program Files\Atmel\AVR Tools\AVR Toolchain\bin\make.exe
Loaded plugin AVR GCC
Loaded partfile: C:\Program Files\Atmel\AVR Tools\PartDescriptionFiles\ATtiny2313.xml
Flash memory 2048
EEPROM memory 128
I/O memory start 0x20
I/O start 0x00
I/O stop 0x3F
SRAM size 128
SRAM start 0x60
XRAM size 0
Temporary page buffer 32
SRAM start NA
No of registers 32
Start Address registers 0x00
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
Flash memory 2048
EEPROM memory 128
I/O memory start 0x20
I/O start 0x00
I/O stop 0x3F
SRAM size 128
SRAM start 0x60
XRAM size 0
Temporary page buffer 32
SRAM start NA
No of registers 32
Start Address registers 0x00
Loaded plugin AVR GCC
Loaded partfile: C:\Program Files\Atmel\AVR Tools\PartDescriptionFiles\ATtiny2313.xml
Flash memory 2048
EEPROM memory 128
I/O memory start 0x20
I/O start 0x00
I/O stop 0x3F
SRAM size 128
SRAM start 0x60
XRAM size 0
Temporary page buffer 32
SRAM start NA
No of registers 32
Start Address registers 0x00
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
gcc plug-in: CProjectTree::OnSize()
Flash memory 2048
EEPROM memory 128
I/O memory start 0x20
I/O start 0x00
I/O stop 0x3F
SRAM size 128
SRAM start 0x60
XRAM size 0
Temporary page buffer 32
SRAM start NA
No of registers 32
Start Address registers 0x00
gcc plug-in: BuildProject() : Finished building project
AVR Simulator: Please wait while configuring simulator...
AVR Simulator: EEPROM: 128 bytes, EECR at 0x1C, interrupt at 0x0011. MPE/MWE: yes, PM: yes
AVR Simulator: IO Module: PORTA created !
AVR Simulator: IO Module: PORTB created !
AVR Simulator: IO Module: PORTD created !
AVR Simulator: IO Module: EXTINT0 created !
AVR Simulator: IO Module: EXTINT1 created !
AVR Simulator: IO Module: PININT0 created !
AVR Simulator: IO Module: TIMER0 created !
AVR Simulator: IO Module: TIMER1 created !
AVR Simulator: IO Module: ANALOGCOMP created !
AVR Simulator: IO Module: USART created !
AVR Simulator: IO Module: USI created !
AVR Simulator: ATtiny2313 Configured OK
Flash memory 2048
EEPROM memory 128
I/O memory start 0x20
I/O start 0x00
I/O stop 0x3F
SRAM size 128
SRAM start 0x60
XRAM size 0
Temporary page buffer 32
SRAM start NA
No of registers 32
Start Address registers 0x00
The contents of the objectfile exceeds the maximum program memory of the device
Error loading object file D:\Radio\Proba\povorot1\default\povorot1.elf
sigmaN
вы издеваетесь?
Цитата
The contents of the objectfile exceeds the maximum program memory of the device
какое из этих слов вы не смогли перевести?

оптимизацию -Os включите для начала. авось влезет таки.
Чё-та лога самой компиляции не видно... delay.h наверняка ругается, что оптимизации нет, а мой приём для обхода этой непрятной ситуации - вы почему-то выбросили и инклюдите delay.h прямо так. вот и получайте ))

а ещё для верности найти надо в папке с проектом(скорее подпапка default) файл с расширением .map и глянуть чё к чему там
RW6MKA
Цитата
вы издеваетесь?
Цитата
The contents of the objectfile exceeds the maximum program memory of the device
какое из этих слов вы не смогли перевести?

Да нет,вы не так поняли.Перевёл я всё это прекрасно,просто не пойму почему авторскому варианту памяти хватает,а моему нет.Хотя мой вариант короче.
Цитата
оптимизацию -Os включите для начала. авось влезет таки.
Чё-та лога самой компиляции не видно... delay.h наверняка ругается, что оптимизации нет, а мой приём для обхода этой непрятной ситуации - вы почему-то выбросили и инклюдите delay.h прямо так. вот и получайте ))

Оптимизация итак включена,а компилятор сам не ругается,он благополучно всё компилит(ну за исключением)
Цитата
../povorot1.c:27: warning: return type of 'main' is not 'int'
Вот когда включаешь Build and Run,тогда он и ругается.
И подскажите,как быть с
Код
if ((PIND6==0)|(Analog()>23))
Ведь в самом начале чтобы пройти эту проверку Analog() должна иметь какоето значение,а питание на датчик ещё не подано(только после нажатия любой кнопки)
sigmaN
.map файл приведите.
я не знаю что там у вас за проверки... может быть будем пытаться решать проблемы по мере их поступления...
RW6MKA
Что то я такого файла не наблюдаю.Вот на всякий случай вся папка с проектом.Нажмите для просмотра прикрепленного файла
sigmaN
ну так скомпилить надо, чтоб появился ))

да тут и .map смотреть не нужно
компилим, смотрим
Цитата
AVR Memory Usage
----------------
Device: attiny2313

Program: 3572 bytes (174.4% Full)
(.text + .data + .bootloader)

Data: 267 bytes (208.6% Full)
(.data + .bss + .noinit)
ну не влазит, что ж тут сказать ))

блин, думал это delay.h тянет за собой плавучку, а у вас оказывается прям в коде m=(n-18)/4.82;:
Код
void Led_Pos(void){      //перевод тиков в код светодиода и группы
   uint16_t n;
   uint8_t m;
   n=Analog();           //получаем тики
   m=(n-18)/4.82;        //переводим тики в номер положения переменника
   Led[0]=1<<((m-1)>>(8*(m>>3))); //переводим номер положения переменника в номер светодиода в группе
   Led[1]=~(1<<m/8);     //переводим номер положения переменника в номер группы с инверсией битов
}

так делать не нужно.
вы можете безболезненно написать такое только для архитектуры с аппаратным FPU. для восьмибитников же любая плавучка - это убийство. Она начинает эмулироваться программно, отхавывая всю память, а ещё жутко тормозит. вот.

И вообще, кажется вы тут чё-то немного забурились... вам бы код почистить, а заодно с ним и мысли(идеи)..
разбить вашу задачу на подзадачи(подсистемы), отладить их по отдельности, стараясь писать простой, оптимальный код. А потом уж всё вместе собрать. А так вы что-то кажется не отладив толком одно - кидаетесь к другому...потом тут-же лепите это в программу, выкладываете код с вопросом ну как типа? Да никак. Всё в одной куче )
RW6MKA
Цитата
И вообще, кажется вы тут чё-то немного забурились... вам бы код почистить, а заодно с ним и мысли(идеи)..
разбить вашу задачу на подзадачи(подсистемы), отладить их по отдельности, стараясь писать простой, оптимальный код.
Так подскажите в какую сторону рыть. sad.gif В Analog() вроде нормально. Всё что касается регистров тож вроде ничего лишнего(можно конечно строб и цлк вместо функций в дефайне определить,но уменьшется ли объём отнимаемой памяти?). Ну а что в Led_Pos() такой трабл с делением,да ещё и на нецелочисленное значение,так я не могу ничего придумать wacko.gif как это обойти T=4.82N+18,где Т кол-во тиков N номер положения ручки переменника.Ну вот такой коэффициент у этой зависимости, а округление его до 5 слишком большая погрешность. Что же касается основного цикла программы, то это конечно не окончательный вариант, поэтому я и прошу посмотреть код и подсказать что можно оставить, а что можно и улучшить(форум то в помощь начинающим) rolleyes.gif .
sigmaN
Я канеш неграмотный и тупой, но мне до сих пор не понятно как же там получается у Вас линейная зависимость времени заряда RC цепочки и напряжения...я как-то вот пока не понимаю как такое может случиться?
http://easyelectronics.ru/kondensator-i-rc-cepochka.html
RW6MKA
Я читал эту статью,ссылку на неё вы давали ранее, но вот результаты моих замеров.Нажмите для просмотра прикрепленного файла
Кстати поменял выражение m=(n-18)/4.82 на m=(n-18)*100/482 и компилятор перестал ругаться
sigmaN
Сколько ноликов и еденичек ))
Ручной труд ценится при изготовлении обуви. В нашем случае - пустая трата времени.

Вот не знаю я...какие-то странные результаты...tcnt0 прям как по струнке выстроились... поразительно!

Цитата
Кстати поменял выражение m=(n-18)/4.82 на m=(n-18)*100/482 и компилятор перестал ругаться
вашему процу было бы ещё проще, если бы деление производилось на степень двойки(на 128 например). Тогда вся операция сводилась бы к сдвигу вправо и заняла бы считаные такты ))
RW6MKA
Цитата
Вот не знаю я...какие-то странные результаты...tcnt0 прям как по струнке выстроились... поразительно!

Меня это то же наводит на грустные мысли,и мне кажется что придётся всё это собирать в железе и тогда уже считать диапазон TCNT0.Видимо заряд конденсатора в Протеусе идёт не по экспоненте((


Вот,хотелось бы узнать ваше мнение
Код
   sei();
   CD4094_init();

while(1){


      if((PIND6==0)||(PIND4==0)){
         Led_Pos();
         Shift_Reg();
         if ((PIND6==0)|(TCNT0>20)){    //если кнопка S0(см.схему) нажата и вращение в эту сторону не дошло до конца
         OnBit(PORTD,2);   //включить поворот (RUN)
         OffBit(PORTD,1);  //реверс не включать
         }                
         if ((PIND4==0)|(TH<0)|(TCNT0<5)){    //если кнопка S2 нажата и вращение в эту сторону не дошло до конца
         OnBit(PORTD,2);   //включить поворот
         OnBit(PORTD,1);   //включить реверс(REV)
         }
      }
   }
}


Да,вот что хотел ещё добавить.Почему то зависает отладка в конце выполнения CD4094_init();Раньше такого не было wacko.gif
sigmaN
В приведенном Вами коде использовать TH и TCNT0 в условиях - не самая лучшая идея.
Я бы завел переменную типа 0 - разрешено движение в обе стороны, 1 - только влево 2 - только вправо.

Нужно всегда помнить о таком понятии, как уровни абстракции и атомарность доступа к данным.
Также я вам давал ссылку на что-то типа этого http://blog.evseev.ru/2009/11/high-cohesio...w-coupling.html

Я думаю, правильно было бы в главном цикле уже отвязаться от регистров и магических чисел типа TCNT0>20
Вся грязная(низкоуровневая) работа должна быть сосредоточена в коде драйвера, драйвер же должен предоставлять простой интерфейс в виде функций и переменных,если это возможно - т.е. чтение переменной в любой момент времени даст правильные результаты. В ином случае надо предусмотреть функцию чтения значения этой переменной, которая выполнит необходимые блокировки или проверки и выдаст правильное значение или код ошибки.
Таким образом достигаются основные цели
1. Код, использующий этот драйвер не знает и не зависит от того, как этот драйвер устроен внутри.
Второе вытекает из первого: в любой момент можно переписать реализацию драйвера или вовсе сменить оборудование(компаратор на АЦП) и если соблюсти описаный ранее интерфейс - вам не придётся ничего переписывать в вышестоящем уровне абстракции(в цикле, релизующем конечный автомат состояний устройства)

Именно поэтому сначала приступают к проектированию этих самых модулей и интерфейсов. Если на пальцах: их взаимодействия на основании того, что от кого и в какие моменты времени будет нужно. Далее думают кто и в каком виде может это дать.. ))

В случае, когда вы имеете дело с жесткими ограничениями ресурсов - вы должны всегда искать компромисс между слишком сильной абстракцией и недостаточной(когда всё везде повязано друг на друга и только что-то измени - всё рушится). Кроме того, никогда не стоит забывать о портируемости. Завтра вы возьмете Мегу8 вместо вашей Тиньки и будете всё делать по новой. В грамотно спроектированной программе придётся заменить только аппаратно зависимую часть(работа с переферией).
Об этом нужно думать всегда.

Про атомарность доступа почитайте хотя-бы на томже изиэлектроникс.ру.. точно помню там статью.
Вот этого вам нехватает кажется )
RW6MKA
Цитата
В приведенном Вами коде использовать TH и TCNT0 в условиях - не самая лучшая идея.
Я бы завел переменную типа 0 - разрешено движение в обе стороны, 1 - только влево 2 - только вправо.

Я решил поступить примерно так же,но тут столкнулся с проблемой.Что бы установить статус(0,1,2) мне нужно прогнать Analog() но без включения любой кнопки эта функция повиснет(нет напряжения с датчика),а кнопку не включишь без проверки статуса.Какой то замкнутый круг получается.((
sigmaN
Всё в Ваших руках ))
RW6MKA
Всем с Новым годом! Вот,столкнулся с банальной проблемой, а решить не могу. В коде кнопки не работают. Для выяснения причины был написан отдельный код
Код
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>


#define  OnBit(address,bit) (address|=(1<<bit))
#define  OffBit(address,bit) (address&=~(1<<bit))




void main(void){

    // инициализация порта D                
   DDRD=0x06;
   PORTD=0x40;
  
  
   while(1){
      if(PIND6==0){
      
      OnBit(PORTD,1);
      _delay_ms(1000);
      OffBit(PORTD,1);
      _delay_ms(1000);
      OnBit(PORTD,2);
      _delay_ms(1000);
      OffBit(PORTD,2);
      _delay_ms(1000);
      }
   }
}
в котором нажатием кнопки включается мигалка. Всё это смоделировано в Протеусе и нифига не работает. Кнопка нажимается, а PIND помоему не читается(если убрать условие проверки то цикл работает) ??????Что это? Глюк Протеуса?
sigmaN
Что-то вот никак у Вас не получается мыслить "по программерски".
Объявление PIND6 смотрели?
С:\Program Files\Atmel\AVR Tools\AVR Toolchain\avr\include\avr\iotn2313.h
Код
#define PIND6   6


итого Ваш
Код
if(PIND6==0){
превращается в
Код
if(6==0){


Вопросы, жалобы, предложения?

Элементарный случай.
Блин, да вы вообще отладкой не занимаетесь значит. Это ужасно.
RW6MKA
Цитата
Что-то вот никак у Вас не получается мыслить "по программерски".
Объявление PIND6 смотрели?
Да еслиб я знал что в все инклуды разные wacko.gif В CV AVR например такого дефайна нет.
Цитата
Блин, да вы вообще отладкой не занимаетесь значит. Это ужасно.
Да я весь инет перелопатил в поисках этого PIND6==0, (ну не догадался я заглянуть в iotn2313.h) и только сегодня утром узнал,что в студии такое выражение не катит и его принято заменять на (!(PIND&0x40)). Занимаюсь я отладкой,только понятно что в меру своих познаний, и зачастую просто не знаю где искать. crying.gif
sigmaN
PIND6 создан для того, чтобы не писать магических чисел как вы !(PIND & 0x40) а написать !(PIND & 1 << PIND6)
т.е. он просто содержит номер бита, отвечающего за пин номер 6 в регистре PIND. от того и название у него такое - PIND6))
RW6MKA
Всё, башка больше не рубит. wacko.gif Объясните мне тупому smile3046.gif почему этот код не хочет выполняться по порядку, как положено любому добропорядочному коду????????
CODE
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CD4094_PORT PORTB
#define CD4094_DDR DDRB
#define CD4094_PIN_DATA 3
#define CD4094_PIN_CLK 2
#define CD4094_PIN_STB 4
#define OnBit(address,bit) (address|=(1<<bit))
#define OffBit(address,bit) (address&=~(1<<bit))
#define Rstop 1
#define Lstop 2
#define Run 0
//объявление прототипов функций
void CD4094_init(void);
void CD4094_CLK(void);
void CD4094_STB(void);
void Shift_Reg(void);
void Shift_One_Byte(uint8_t r);
uint16_t Analog(void);
uint8_t Datchik_Pos(void);
void Led_Pos(void);
void RotorL(void);
void RotorR(void);

//определение переменных
volatile uint8_t TH;
uint8_t Led[2];
uint8_t Povorot;
uint8_t N;

void main(void){

// инициализация порта D и B
PORTD=0x70; //установка битов порта D в 0 или 1
DDRD=0x06; //установка порта D на in или out
DDRB=0x1C; //установка stb,data,clk на выход,уровень 0


//инициализация прерываний по переполнению таймера0
TIMSK=0x2;

//инициализация аналогового компаратора
ACSR=0x00;

Led[0]=Led[1]=0;
Povorot=0;
N=0;
CD4094_init(); //инициализация регистров
OffBit(DDRB,7); //выключаем транзистор
OnBit(DDRB,0); //разряжаем кондёр
_delay_ms(2); //время для разряда кондёраPovorot=0;
sei(); //разрешение глобальных прерываний

//основной цикл
while(1){
if((!(PIND&1<<PIND6))||(!(PIND&1<<PIND4))){ //если нажата одна из кнопок
N=Datchik_Pos();
if(N<1) Povorot=Rstop; //определение конечного правого положения датчика
else if(N>48) Povorot=Lstop; //определение конечного левого положения датчика
else Povorot=Run;
if(!(PIND&1<<PIND6)) RotorR(); //если нажата кнопка S0
if(!(PIND&1<<PIND4)) RotorL(); //если нажата кнопка S2
}
else {OffBit(PORTD,1);OffBit(PORTD,2);} //если не нажата ни одна из кнопок
}
}

void RotorR(void){
if(Povorot==Rstop){
OffBit(PORTD,2);
OffBit(PORTD,1);
return;} //если в крайнем правом положении то стоп
else{
OnBit(PORTD,2); //включить поворот (RUN)
OffBit(PORTD,1); //реверс не включать
Datchik_Pos();
Led_Pos();
Shift_Reg();
_delay_ms(300);
}
}

void RotorL(void){
if(Povorot==Lstop){
OffBit(PORTD,1);
OffBit(PORTD,2);
return;} //если в крайнем левом положении то стоп
else{
OnBit(PORTD,2); //включить поворот (RUN)
OnBit(PORTD,1); //реверс включить
Datchik_Pos();
Led_Pos();
Shift_Reg();
_delay_ms(300);
}
}

uint8_t Datchik_Pos(void){ //перевод тиков в номер положения датчика
uint16_t n;
uint8_t m;
n=Analog(); //получаем тики
m=((n-30)*100)/476; //переводим тики в номер положения переменника
return(m);
}

void Led_Pos(void){ //перевод номера положения датчика в код светодиода и группы
uint8_t m;
m=Datchik_Pos();
Led[0]=(1<<((m-(((m-1)>>3)<<3))-1)); //переводим номер положения переменника в номер светодиода в группе
Led[1]=~(1<<((m-1)>>3)); //переводим номер положения переменника в номер группы с инверсией битов
}


void CD4094_init(void){ //инициализация регистров
uint16_t i;
for(i=0;i<16;i++){OffBit(CD4094_PORT,CD4094_PIN_DATA) ; CD4094_CLK(); }
}

void CD4094_CLK(void){ //дёргаем ногу clk для проталкивания битов по регистру
OnBit(CD4094_PORT,CD4094_PIN_CLK);
_delay_us(15);
OffBit(CD4094_PORT,CD4094_PIN_CLK);

}

void CD4094_STB(void){ //дёргаем ногу stb для поджига светодиодов
OnBit(CD4094_PORT,CD4094_PIN_STB);
_delay_us(10);
OffBit(CD4094_PORT,CD4094_PIN_STB);

}

void Shift_Reg(void){ //загрузка сдвигового регистра
Shift_One_Byte(Led[1]);//загрузка кода группы в регистр
Shift_One_Byte(Led[0]);//загрузка кода светодиода в группе регистр
OffBit(CD4094_PORT,CD4094_PIN_DATA);
CD4094_STB(); //зажигаем светодиоды
}

void Shift_One_Byte(uint8_t r){ //загрузка одного байта
uint8_t i=8;
while(i--){
if(r&0x80) OnBit(CD4094_PORT,CD4094_PIN_DATA);
else OffBit(CD4094_PORT,CD4094_PIN_DATA);
CD4094_CLK();
r<<=1;
}
}

uint16_t Analog(void){ //используем аналоговый компаратор для замера времени заряда кондёра
OffBit(DDRB,0); //переводим 0 выход порта В в третье состояние
TCNT0=0; //очистим счётчик-накопитель
TH=0;
TCCR0B=2; //включаем таймер0 с пределителем CLK/8
OnBit(DDRB,7); //включить транзистор
while(!(ACSR&(1<<ACO))); //ждём изменения состояния бита АСО на выходе компаратора
TCCR0B=0; //выключаем таймер
OffBit(DDRB,7); //выключаем транзистор
OnBit(DDRB,0); //разряжаем кондёр
_delay_ms(2); //время для разряда кондёра
return(TH<<8|TCNT0); //возвращаем результат замера времени
}

ISR(TIMER0_OVF_vect){ //обработка прерывания таймера0 по переполнению
//при переполнении 8-битного счётчика таймера увеличивать байт ТН на 1
TH++;
}








Почему эта зараза при заходе в главный цикл не проверяет условие первого if, а сразу лезет к else if(N>48)??????? И вообще при шаговом выполнении наблюдаются скачки в такие места кода, куда даже "Макар телят не гонял" biggrin.gif А когда я попробовал вместо Analog() вставить просто число что бы прогнать код по функциям, то он наотрез отказался заходить в Datchik_Pos(). Блок
Код
N=Datchik_Pos();
         if(N<1) Povorot=Rstop; //определение конечного правого положения датчика
         else if(N>48) Povorot=Lstop; //определение конечного левого положения датчика
         else Povorot=Run;
я пробовал заменить функцией - вообще код сбрендил и прыгал куда попало. Вообщем это не отладка кода, а отладка моей нервенной очень системы rolleyes.gif
sigmaN
для начала проверьте отключена ли у вас оптимизация( -O0 )
с оптимизацией код и будет прыгать куда даже "Макар телят не гонял" biggrin.gif

Форматирование кода у вас никуда не годится. почитали бы Вы немного по стандартам кодирования наверно...
RW6MKA
Цитата
Форматирование кода у вас никуда не годится.
А что конкретно не так. Вроде старался всё по своим местам поставить?! laughing.gif
Цитата
для начала проверьте отключена ли у вас оптимизация( -O0 )

Оптимизацию отключил, но всё осталось как прежде crying.gif

Вот ещё чё заметил,если привести код к такому виду,то более-менее процесс идёт
Код
//инициализация аналогового компаратора
   ACSR=0x00;

   sei();                 //разрешение глобальных прерываний
   CD4094_init();         //инициализация регистров
   Povorot=0;
  

   //основной цикл
   while(1){
      if((!(PIND&1<<PIND6))||(!(PIND&1<<PIND4))){  //если нажата одна из кнопок
         N=Datchik_Pos();
         if(N<1) Povorot=Rstop; //определение конечного правого положения датчика
         else if(N>48) Povorot=Lstop; //определение конечного левого положения датчика
         else Povorot=Run;
         if(!(PIND&1<<PIND6)) RotorR(); //если нажата кнопка S0
         if(!(PIND&1<<PIND4)) RotorL(); //если нажата кнопка S2
      }
      else {OffBit(PORTD,1);OffBit(PORTD,2);}  //если не нажата ни одна из кнопок
   }
}
хотя прыжок сразу на else if(N>48)
sigmaN
Организуйте для начала нормальный отладочный вывод, чтобы не шагами шагать, а реально в проге было видно чё куда и как. Зашел в if - зажглись диодеги соответствующие. Вышел - погасли и т.д. а то вообще не понятно чему там в действительности ваша N равно вначале....
не очень то полагайтесь на все эти шаги... или шагайте там, где вместе с Си кодом - асм видно. тогда уж сможете сориентироваться хоть как-то...
прыжок на строку с if ещё не означает, что выполнился блок кода, который под этим if. а уж с вашим форматированием всё в кучу - так и вообще не понять ничего....
заверните вот так
if(N<1)
{
Povorot=Rstop; //определение конечного правого положения датчика
}
а Povorot в Watch и наблюдайте. вот если реально Povorot изменился - значит попал в if. ну и т.д.
самый надежный канеш вариант - это отладочный вывод прямо из работающей программы(задержки добавить если чё).
Было-бы идеально, если бы у вас был UART(но можно софтовый наверно приладить) и вы прямо выводили человеческим языком отладочную инфу прямо на терминал ) Но тут то можно и диодегами обойтись. Благо у вас их ооочень много там )
XVR
Цитата
хотя прыжок сразу на else if(N>48)
Прыжок у вас скорее всего на else перед if (N>=48). Похоже if (N<1) не сработал, а компилятор вероятно привязал номера строк к веткам then и else (для if места не нашлось sm.gif )
Переформатируйте код, как советовал sigmaN, возможно начнет ходить нормально
RW6MKA
Цитата
Переформатируйте код, как советовал sigmaN, возможно начнет ходить нормально
Не совсем , сначала прыгает на N=Datchik_Pos(); а потом возвращается в начало и всё идёт по порядку,как надо.

Цитата
Организуйте для начала нормальный отладочный вывод, чтобы не шагами шагать, а реально в проге было видно чё куда и как. Зашел в if - зажглись диодеги соответствующие.
Поясните,как это сделать в студии?

Кстати залил всё в железо, индикация вроде нормальная,а вот реализация концевых ограничений где то глючит, да и с самими кнопками...Сразу после включения срабатывает только кнопка поворота вправо(PIND6, а по коду вроде всё нормально?). При прохождении вправо до срабатывания концевика реле начинает дёргатся, вместо того что бы просто выключится( опять же в коде такого не наблюдал,всё послушно шагает по циклу).Включаем вращение влево, уводим датчик от конца и нажимаем опять вращение вправо и понимаем что срабатывает не всегда(такое ощущение что где то нужна задержка). так же и в другую сторону.
sigmaN
Цитата
Поясните,как это сделать в студии?
также как и не в студии)) тут вообще без привязки к языку даже))

Цитата
а вот реализация концевых ограничений где то глючит
ну по науке вам не хватает гистерезиса. Т.е. допустим в попугаях 0 - это крайнее левое положение. Так вот надо сделать так, что бы вращение влево прекращалось при достижении значения 1(условно), а вот если мы однажды запретили движение влево - то разрешать его нужно только если мы уже прошли(вправо) до значения 7(опять таки условно).
Т.е. обеспечить зазор на погрешности и механические неточности/инерцию...


А ещё, при всём при этом должна быть чётко отлажена процедура замера положения. Опять таки тут нужно определиться с необходимой и достаточной частотой опроса + отфильтровать значения(если будет такая необходимость) хотя-бы вычисляя среднее по трём-пяти(двум или восьми) считанным значениям.

Цитата
Сразу после включения срабатывает только кнопка поворота вправо(PIND6, а по коду вроде всё нормально?).
ну если было бы нормально - оно бы работало )) ищите)) и нормально код переформатируйте! неудобно же самому разбираться даже в этих ифах налеплных в одну строку и в кучу. Отступы, отступы. Пробелы где надо должны быть.
еслиявоттаквотписатьбуду-этоженебудетнормальночитаться,хотявсебуквыинаместевродекакискомпилитьсядолжноваш
иммоском)))
RW6MKA
Вот, вроде всё привёл к нормальному стилю(ежели что не так тыкнете носом)
CODE
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CD4094_PORT PORTB
#define CD4094_DDR DDRB
#define CD4094_PIN_DATA 3
#define CD4094_PIN_CLK 2
#define CD4094_PIN_STB 4
#define OnBit(address,bit) (address|=(1<<bit))
#define OffBit(address,bit) (address&=~(1<<bit))
#define Rstop 1
#define Lstop 2
#define RUN 2
#define REV 1
#define S0 6
#define S2 4

//объявление прототипов функций
void CD4094_init(void);
void CD4094_CLK(void);
void CD4094_STB(void);
void Shift_Reg(void);
void Shift_One_Byte(uint8_t r);
uint16_t Analog(void);
uint8_t Datchik_Pos(void);
void Led_Pos(void);
void RotorL(void);
void RotorR(void);

//определение переменных
volatile uint8_t TH;
uint8_t Led[2];
uint8_t Povorot;
uint8_t N;

void main(void) {

// инициализация порта D и B
PORTD = ((1 << S0) | (1 << S2)); //включение подтягивающих резисторов в S0,S2
DDRD = ((1 << RUN) | (1 << REV)); //установка RUN,REV на выход
DDRB = ((1 << CD4094_PIN_DATA) | (1 << CD4094_PIN_CLK) | (1 << CD4094_PIN_STB)); //установка stb,data,clk на выход,уровень 0

//инициализация прерываний по переполнению таймера0
TIMSK = 0x2;

//инициализация аналогового компаратора
ACSR = 0x00;

sei(); //разрешение глобальных прерываний
CD4094_init(); //инициализация регистров
Led[0] = 0;
Led[1] = 0;
Povorot = 0;


//основной цикл
while (1) {
if ((!(PIND & 1 << PIND6)) || (!(PIND & 1 << PIND4))) { //если нажата одна из кнопок
N = Datchik_Pos();
if (N > 48) { //определение конечного правого положения датчика
Povorot = Rstop;
} else if (N < 1) { //определение конечного левого положения датчика
Povorot = Lstop;
} else if ((N > 1) && (N < 48)) {
Povorot = 0;
}
if (!(PIND & 1 << PIND6)) { //если нажата кнопка S0
RotorR();
}
if (!(PIND & 1 << PIND4)) { //если нажата кнопка S2
RotorL();
}
} else { //если не нажата ни одна из кнопок
OffBit(PORTD, REV);
OffBit(PORTD, RUN);
}
}
}


void RotorR(void) {
if (Povorot == Rstop) { //если в крайнем правом положении то стоп
OffBit(PORTD, RUN);
OffBit(PORTD, REV);
_delay_ms(300);
return;
} else {
OnBit(PORTD, RUN); //включить поворот (RUN)
OffBit(PORTD, REV); //реверс не включать (REV)
Led_Pos();
Shift_Reg();
_delay_ms(300);
}
}


void RotorL(void) {
if (Povorot == Lstop) { //если в крайнем левом положении то стоп
OffBit(PORTD, RUN);
OffBit(PORTD, REV);
_delay_ms(300);
return;
} else {
OnBit(PORTD, RUN); //включить поворот (RUN)
OnBit(PORTD, REV); //реверс включить (REV)
Led_Pos();
Shift_Reg();
_delay_ms(300);
}
}


uint8_t Datchik_Pos(void) { //перевод тиков в номер положения датчика
uint16_t n = 0;
uint16_t i;
uint8_t m = 8;
while(m--) {
n += Analog(); //накапливаем тики
}
i = n>>3; //получаем средние тики
m = ((i - 36) * 100) / 474; //переводим тики в номер положения переменника
return (m);
}


void Led_Pos(void) { //перевод номера положения датчика в код светодиода и группы
uint8_t m;
m = Datchik_Pos();
Led[0] = (1 << ((m - (((m - 1) >> 3) << 3)) - 1)); //переводим номер положения переменника в номер светодиода в группе
Led[1] = ~(1 << ((m - 1) >> 3)); //переводим номер положения переменника в номер группы с инверсией битов
}


void CD4094_init(void) { //инициализация регистров
uint16_t i;
for(i = 0; i < 16; i++) {
OffBit(CD4094_PORT, CD4094_PIN_DATA);
CD4094_CLK();
}
}


void CD4094_CLK(void) { //дёргаем ногу clk для проталкивания битов по регистру
OnBit(CD4094_PORT, CD4094_PIN_CLK);
_delay_us(15);
OffBit(CD4094_PORT, CD4094_PIN_CLK);

}


void CD4094_STB(void) { //дёргаем ногу stb для поджига светодиодов
OnBit(CD4094_PORT, CD4094_PIN_STB);
_delay_us(10);
OffBit(CD4094_PORT, CD4094_PIN_STB);

}


void Shift_Reg(void) { //загрузка сдвигового регистра
Shift_One_Byte(Led[1]);//загрузка кода группы в регистр
Shift_One_Byte(Led[0]);//загрузка кода светодиода в группе регистр
OffBit(CD4094_PORT, CD4094_PIN_DATA);
CD4094_STB(); //зажигаем светодиоды
}


void Shift_One_Byte(uint8_t r) { //загрузка одного байта
uint8_t i = 8;
while(i--) {
if (r&0x80) {
OnBit(CD4094_PORT, CD4094_PIN_DATA);
} else {
OffBit(CD4094_PORT, CD4094_PIN_DATA);
}
CD4094_CLK();
r <<= 1;
}
}


uint16_t Analog(void) { //используем аналоговый компаратор для замера времени заряда кондёра
OffBit(DDRB, 0); //переводим 0 выход порта В в третье состояние
TCNT0 = 0; //очистим счётчик-накопитель
TH = 0;
OnBit(TCCR0B, CS01); //включаем таймер0 с пределителем CLK/8
OnBit(DDRB,7); //включить транзистор
while(!(ACSR &(1 << ACO)));//ждём изменения состояния бита АСО на выходе компаратора
OffBit(TCCR0B, CS01); //выключаем таймер
OffBit(DDRB, 7); //выключаем транзистор
OnBit(DDRB, 0); //разряжаем кондёр
_delay_ms(2); //время для разряда кондёра
return(TH << 8 | TCNT0); //возвращаем результат замера времени
}


ISR(TIMER0_OVF_vect) { //обработка прерывания таймера0 по переполнению
//при переполнении 8-битного счётчика таймера увеличивать байт ТН на 1
TH++;
}

Что касается исполнения кода, то прыжок с Povorot = 0; сразу на Povorot = Lstop; потом на Povorot = Rstop; и только после этого на if ((!(PIND & 1 << PIND6)) || (!(PIND & 1 << PIND4))) { // я не могу объяснить никак. Потом до момента получения среднего числа тиков всё идёт гладко и опять необъяснимый скачок на } else { //если не нажата ни одна из кнопок
OffBit(PORTD, REV);
OffBit(PORTD, RUN); (именно на выключение RUN) и дальше опять всё нормально. Что за скакалки-прыгалки?
XVR
'Нормальный стиль' - это
Код
N = Datchik_Pos();
if (N > 48)
{ //определение конечного правого положения датчика
  Povorot = Rstop;
}
else
if (N < 1)
{ //определение конечного левого положения датчика
  Povorot = Lstop;
}
else
if ((N > 1) && (N < 48))
{
  Povorot = 0;
}

По крайней мере не будет неопределенности с номерами строк (со стороны компилятора)
sigmaN
обязательно скурить:
http://easyelectronics.ru/avr-uchebnyj-kur...mm-chast-1.html
http://easyelectronics.ru/avr-uchebnyj-kur...mm-chast-2.html
http://easyelectronics.ru/avr-uchebnyj-kur...mm-chast-3.html
http://easyelectronics.ru/avr-uchebnyj-kur...mm-chast-4.html
и то, что там всё на асме - не так уж и важно, ибо сам подход остаётся тем-же и для Си

и вот это вот тоже осмыслить бы и применить на практике:
http://easyelectronics.ru/avr-uchebnyj-kur...yj-avtomat.html

ну не знаю....тоже отладка... сам не читал...
http://easyelectronics.ru/vnutrisxemnaya-o...z-jtag-ice.html
RW6MKA
Цитата
По крайней мере не будет неопределенности с номерами строк (со стороны компилятора)
Пробовал и так, результат тот же.

Цитата
обязательно скурить:
Так я этими статьями и пользуюсь. Больше по студии и почитать особо негде.
Цитата
и вот это вот тоже осмыслить бы и применить на практике:
Это я так понимаю к вопросу о гистерезисе? Пока отложу, надо разобраться с тем что есть.
Цитата
ну не знаю....тоже отладка... сам не читал...
Штука классная, но у меня тинька. crying.gif
Теперь вопрос. Прогнал код и вдоль и поперёк. Все пины, таймер,прерывание ну всё показывает нормально, а логики этих скачков не могу ни понять, ни отследить в чём причина. Как это побороть? smile3009.gif
sigmaN
Цитата
Это я так понимаю к вопросу о гистерезисе? Пока отложу, надо разобраться с тем что есть.
это к вопросу о том, что разрабатываемое вами устройство - есть не более чем конечный автомат )))

ну глючит там отладчик при шагах по си коду...что вы так на этом зацикливаетесь то а?
я уже предлагал ведь вам организовать отладочный вывод и по нему определиться, правильно ли выполняется программа.
ну + задержки где надо, чтоб успевать соображать что к чему.... и прямо на ходу всё проверите.


выкладывайте проект + протеусовский тоже.
XVR
Это работа оптимизатора (посмотрите ассемблер). Он вынес константы Lstop и Rstop (для их последующего присваивания в Povorot) на регистры, и загрузку этих регистров константами (перед циклом) привязал к строкам Povorot = Lstop; и Povorot = Lstop;
Вот он по ним и прыгает
Далее идет нормальный код, т.ч. первые прыжки можете игнорировать

RW6MKA
Цитата
Это работа оптимизатора (посмотрите ассемблер).
Так и не понял как это сделать в студии. sad.gif Да, а оптимизация то отключена blink.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.