Перейти к содержанию

Владислав Бобриков

Members
  • Постов

    23
  • Зарегистрирован

  • Посещение

Весь контент Владислав Бобриков

  1. Я имел ввиду, что функция, обрабатывающая прерывания "идет". Кажется до меня немного доходит, то есть если я впишу в прерывание открытие реле, то оно в одном прерывании откроется и будет открытым, независимо от сигнала, а потом в основном цикле программы(по таймеру, без delay), проверить, допустим, через 3 секунды на пине высокий уровень ? тогда оставить реле включенным, если низкий - оффнуть. Или не очень правильно мыслю ?)
  2. ну, прерывание вызывается по нарастающему фронту с датчика холла, если же сигнал на пине, который ответственный за внешнее прерывание, другой, то внешнее прерывание не вызывается
  3. Всем привет ! Программу доделал, устройство на макетной плате собрал, скоро буду в диптрейсе делать разводку реальной платы. Всем спасибо за помощь, скоро выложу все исходники ! Есть последняя проблема, оказывается нужно еще подключить реле, с этим проблем нет, но на катушку реле напряжение с порта(естественно через транзистор) должно подаваться при определенном условии: когда идет вода через датчик воды(в нем датчик холла на каретке). В программе счет проливаемой через датчик воды идет по внешнему прерыванию, но если я втулю открытие порта по прерыванию то реле будет тупо щелкать(потому что прерывания по нарастаящему фронту), но мне нужно сделать так, чтобы допустим вода льется, прерывания идут, тогда реле открыто все время(не щелкая), а когда например прерываний нет, то есть сигнал с датчика это 0, то реле закрыто. Как это реализовать ? Понятия не имею
  4. asm("sei") и asm("cli") , как я понимаю первое это глобальное разрешение, а второе - глобальный запрет ?
  5. Можно ли запрещать и разрешать глобальные прерывания (я так понимаю это команда еще является разрешением прерывания и для таймера) внутри функции, которая используется в главном цикле программы вайл ? Ну то есть, допустим на вход порта Б бита ноль 0 подавалась единица. Вдруг она пропала, флаг стал нулем, описана функция, когда вызывается, если флаг становиться нулем, и в этой функции идет запрет на прерывания, отключения клапана, и крутиться бесконечный цикл, до тех пор, пока уровень на пине б.0 не станет снова высоким ? После того как стал высоким, прерывания разрешаются, флаг становиться единицей и программа выходит из этой функции в основной бесконечный цикл вайл. Или же есть какие-то нюансы по поводу запретов и разрешений внешнего прерывания, и прерывания по переполнению таймера ?
  6. Все уже сделал, заработало, немного стресс, из-за того что сроки скоро подойдут. Сейчас работаю над тем, чтобы глобальное прерывания работало по нарастаящему фронту, когда 450 импульсов проходит, то из двух настроек минусуется единица(что символизирует литр).
  7. Сделал, функция не вызвалась, сразу показало это: eeprom int flagz=0; ... void main{ ScanKeyBoard(flagz); while (1) { ...
  8. еще 2 итерации сделаны для того, чтобы можно было удалить последний символ через клавишу звездочка, и "ввести", то есть подтвердить ввод клавишей решетка. Не могу понять, как сделать, чтобы функция вызывалась единожды. Ну то есть я поместил код опроса клавы в функцию. Аргумент у него некий флаг, внутри функции происходит опрос если флаг==0, а после опроса становиться единицей. флаг занесен в епром. При выключении питания и включении заново происходит снова опрос. Как сделать, чтобы функция ввода значений клавы вызывалась единожды при первом запуске ?
  9. Только что вторую настройку МР сделал флоатом, а следовательно использовал atof и ftoa - все работает.
  10. Блин, возникла та же проблема что и была, с переводом числа. Ну то есть я влезаю в диапазон лонг инт. В первую настройку ввожу 999999 во вторую настройку ввожу 9999 они вводятся в массив, после этого конвертируются в лонг инт, и снова конвертируются, но в другом массив с таким же типом, как и был до этого. этот же код у меня работал до этого, а потом перестал. Вторая настройка, в которой всего 4 разряда, конвертируется так, словно ей не хватает диапазона. (пробовал unsigned и signed) Вот код: #include <mega16.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <delay.h> #include <alcd.h> #include <keyboard.h> eeprom unsigned long int FZ=0; eeprom unsigned long int MR=0; char buf=0; char FZ_[6]; char MR_[4]; char kek[6]; char kek1[4]; int i; unsigned long int temp_FZ=0,TEMP_FZ1=0; unsigned long int temp_MR=0,TEMP_MR1=0; void main(void) { lcd_init(16); KEYB_Init(); while (1) { for( i = 0; i<8; i++) { if(i == 7) { do { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); } while(buf != '#'); break; } do { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); } while(buf == NULL); if(buf == '*') { FZ_[i-1] =' '; lcd_gotoxy(0,1); lcd_putsf("FZ"); lcd_gotoxy((i-1),0); lcd_putchar(FZ_[i-1]); i = i-2; } else { if(i<6) { FZ_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("FZ"); lcd_gotoxy(i,0); lcd_putchar(FZ_[i]); } } } temp_FZ=atol(FZ_); FZ=temp_FZ; TEMP_FZ1=FZ; ltoa(TEMP_FZ1, kek); delay_ms(5000); lcd_clear(); for(i=0;i<6;i++) { if(i == 5) { do { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); } while(buf != '#'); break; } do { KEYB_ScanKeyboard(); buf = KEYB_GetKey(); } while(buf == NULL); if(buf == '*') { MR_[i-1] =' '; lcd_gotoxy(0,1); lcd_putsf("MR"); lcd_gotoxy((i-1),0); lcd_putchar(MR_[i-1]); i = i-2; } else { if(i<4) { MR_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("MR"); lcd_gotoxy(i,0); lcd_putchar(MR_[i]); } } } temp_MR=atol(MR_); MR=temp_MR; TEMP_MR1=MR; ltoa(TEMP_MR1, kek1); delay_ms(5000); lcd_clear(); // lcd_gotoxy(0,0); // lcd_puts(kek); lcd_gotoxy(0,0); lcd_putchar(kek[0]); lcd_gotoxy(1,0); lcd_putchar(kek[1]); lcd_gotoxy(2,0); lcd_putchar(kek[2]); lcd_gotoxy(3,0); lcd_putchar(kek[3]); lcd_gotoxy(4,0); lcd_putchar(kek[4]); lcd_gotoxy(5,0); lcd_putchar(kek[5]); lcd_gotoxy(0,1); lcd_putchar(kek1[0]); lcd_gotoxy(1,1); lcd_putchar(kek1[1]); lcd_gotoxy(2,1); lcd_putchar(kek1[2]); lcd_gotoxy(3,1); lcd_putchar(kek1[3]); } }
  11. Таймер сделал на 1 сек. Обычный. Т.е. прерывания происходят каждую 1 сек. Пытаюсь разобраться как же удалять символы. Ну допустим идет опрос клавиатуры нужно ввести пятизначное число, и ты на 3тьем символе просто ошибся, не будешь же ты вырубать питание и заново писать. Нужно придумать, как удалять символы. Я тут подумал в цикл опроса вставить условие, не нажата ли, например, звездочка. Если нажата, то счетчик цикла декрементируется, а последний записанный символ в массиве (counter-1) становится NULL. Только вот не знаю, как это повлияет на дисплей, если допустим этот алгоритм сработает, удалится число из массива, пропадет ли число на экране дисплея ? Или возможно станет каракулей ?
  12. Ну, это же учебный проект, чем больше извращений, тем больше интересно) А так, скорее всего буду юзать простой таймер
  13. То есть, если установить только один бит WDIE, то собака будет работать в режиме прерывания по истечению, допустим, секунды ?
  14. .epp зашивать так же, как и .hex ? то есть сначала .hex, а потом .epp, или последовательность не важна ? Лол Это как же на вочдоге сделать по переполнению, если он потом просто будет перезагружать контроллер ?)
  15. Всем привет ! Извиняюсь, что давно не было, приехал только с каникул. Так вот, подумал, что лучше будет просто записывать значения раз в два часа. На atmega16a 100к циклов перезаписи в eeprom'e, посчитав понял что хватит на 22 года с лишним. Еще посмотрел тесты памяти епром в Интернете, и если верить этим тестам, то AVR`ки делают с запасом, ну грубо говоря, при записи значений раз в 2 часа получим +-4 года. Возникло пару вопросов: 1) Можно ли сделать таймер, использовав внутренний RC-генератор ? Ну то есть я хочу, чтобы он тикал раз в секунду, или раз в час (хотя это наверное не реально, поэтому просто играясь с переменными можно получить желаемый результат), и будет ли он точным ? Или лучше использовать внешний кварц для бОльшей точности ? 2) Снова еепром. Почитав пару статей, узнал, что помимо .hex файла в контроллер нужно зашивать еще и .epp, который отвечает непосредственно за еепром. Но это говорили больше про программу Poteus, а не про реальные контроллеры (хотя чтобы загрузить этот .epp в Proteus нужно его преобразовать в .bin) . Так вот, нужно ли зашивать .epp в контроллер, и как это сделать ? (Использую AVRFlash от MicroElectrinica, шью через плату EasyAVR v7).
  16. Спасибо) Убрал точку с запятой, получилось вывести на дисплей две настройки, но только посимвольно, потому что функция lcd_puts() выводит чушь на экран, хотя в нее кидаешь эти два массива с записанными значениями. Не могли бы ли вы подсказать пожалуйста, как правильно работать с епром ? То есть перед переменной нужно указать eeprom, или __eeprom, тут вроде бы разницы нет. Попробовал с ней поработать, но почему-то после выключения питания программа снова запрашивает ввод данных, хотя по сути должна показывать то, что записано в еепром на экран сразу, ввел условия if(FZ&&MR==NULL) тогда производить настройку; FZ и MR - переменные епром, в которые записаны значения настроек, после ввода пользователем. Но это почему-то не работает.
  17. В общем, каким-то чудом у меня получило конвернтнуть, вывелось так, как и вводилось. Решил сразу вторую настройку написать, в которой уже не 5 разрядов, а 4. Ок, после первой настройки флаг стал равны единице, переходит во вторую настройку, пишу значение с клавы, ждет, и снова входит во вторую настройку , чтобы ввести значение с клавы. Странно, не могу понять почему происходит это зацикливание, хотя код такой же.. #include <mega16.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <delay.h> #include <alcd.h> #include <keyboard.h> #include <math.h> __eeprom long int FZ, MR; int flag; char buf=0; char FZ_[5]; char MR_[4]; char kek[5]; char kek1[4]; int t; int i; long int temp_FZ,TEMP_FZ1,temp_MR,TEMP_MR1; void main(void) { flag = 0; lcd_init(16); KEYB_Init(); while (1) { if(flag == 0) { for( i = 0; i<5; i++) { check_again: KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if(buf == NULL) goto check_again; FZ_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("FZ"); lcd_gotoxy(i,0); lcd_putchar(FZ_[i]); } flag=1; temp_FZ=atol(FZ_); FZ=temp_FZ; TEMP_FZ1=FZ; ltoa(TEMP_FZ1, kek); delay_ms(5000); lcd_clear(); } if(flag == 1); { flag=2; for(i=0;i<4;i++) { check_again1: KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if(buf == NULL) goto check_again1; MR_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("MR"); lcd_gotoxy(i,0); lcd_putchar(MR_[i]); } temp_MR=atol(MR_); MR=temp_MR; TEMP_MR1=MR; ltoa(TEMP_MR1, kek1); delay_ms(5000); lcd_clear(); } lcd_clear(); lcd_gotoxy(0,0); lcd_puts(kek); lcd_gotoxy(0,1); lcd_puts(kek1); lcd_clear(); } }
  18. Ну в общем идея такая: датчик холла будет стоять на прерывании, то есть, словил сигнал - переменная инкрементировалась, когда переменная достигнет 450, то программа запишет в другую переменную единицу, снова 450 еще плюс единица. То есть датчик холла должен считать с насоса литры, 450 сигналов - один литр. Вот я ввел значение с клавы, сделал его интом, и после этого введенное значение будет вычитать из себя каждый литр воды, и выводить на экран. А так как могут быть перебои в сети, чтобы сохранить введенные значения, буду использовать епром, но загнулся на самом простом - конвертации, по- любому ж нужно конвертировать в инт, чтобы внести в епром и делать расчет, а потом снова в строку, что отобразить на дисплее, ибо функция записи в экран число не принимает. То есть вы предлагаете просто по формуле преобразовать массив в число ? якобы int temp = FZ_[0]*10 000 + FZ_[1]* 1000 и тд. Да, это вариант, но как тогда быть если какой-то разряд числа равен нулю ?
  19. Извините. Вот код: #include <mega16.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <delay.h> #include <alcd.h> #include <keyboard.h> #include <math.h> //__eeprom int FZ, MR; int flag; char buf=0; char FZ_[4]; //char MR_[4]; char kek[4]; int i; unsigned long int temp_FZ; void main(void) { flag = 0; lcd_init(16); KEYB_Init(); while (1) { if(flag == 0) { for( i = 0; i<5; i++) { check_again: KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if(buf == NULL) goto check_again; FZ_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("FZ"); lcd_gotoxy(i,0); lcd_putchar(FZ_[i]); } flag=1; temp_FZ = atol(FZ_); sprintf(kek,"%d", temp_FZ); delay_ms(5000); lcd_clear(); } lcd_gotoxy(0,0); lcd_puts(kek); } } Вот, все настройки регистров убрал. Как видно, в основном цикле вайл, в блок иф входит, когда флаг равен нулю. После этого выполняется сканирование клавиатуры и запись чисел в массив, еще отображение записанного числа на дисплее лсд1602, с этим проблем нет. Опрос закончился, выходим из блока фор, делаем флаг равным одному (чтобы при следующем цикле вайл снова не зашел в блок фор), после этого в переменную типа unsigned long int temp_FZ записываем число, которое ввели в массив, предварительно его конвертировав с помощью atoi() или atol(), ну а потом делается действие наоборот, когда это целочисленное число конвертируется с помощью sprintf или itoa в массив символов, то есть строку, и выводиться н экран дисплея. Но на экран дисплея выводится не то число, которое я ввел. Учел то, что вы написали выше насчет инта, провернув это с лонг и ансигнд лонг интом получилось все тоже самое.
  20. Только что попробовал сделать long int и unsigned long int испольщова atoi и atol, результат такой же, как вы сказали, не влезло - переполнение
  21. Ребята, всем привет ! Вот стоит задача, с матричной клавиатуры считать 5 циферок, и кинуть их в инт, а после этого снова в строку(массив чар) (пишу на си). Суть в том, что пользователь вводит данные с клавиатуры для одной настройки, когда он вводит каждое число присваивается каждому элементу массива. Когда массив заполнен числами, то нужно его конвертировать в число инт, или любое целочисленное, так как потом нужно это число записать в еепром память. использовал функции atoi и itoa( вместо этой еще sprintf), а после конвертации в инт, для теста, решил числа из инта снова в массив чар(строку) конвертить, и вывести. Вывожу конечно же на лсд1602. Работаю в CodeVisionAVR на атмеге16. И все бы ничего, но когда ты вводишь допустим 95430, то по логике, должно же 2 раза конвертнуться, и вывести на лсд тоже самое, но не тут то было, выводит просто рандомное чилсо например -9213 и тд. Не знаю как с этим бороться, обшарил уже весь инет, тут, как в ванильном си шарпе нет методов IntToStr и тд. Еще хочу узнать как правильно работать с епром памятью. Ну то есть вот у меня будет функция на ввод клавиатуры, когда юзер впервые подключит устройство(кстати это курсач такой), он должен будет ввести настройки, после этого, при включении питания девайса, функция опроса клавиатуры и создание этих настроек не должна вызываться. Подумал, и понял что просто сделать флаг на епром, то есть сначала флаг=0, когда равен 0 заходит в первую настройку, когда 1 - во вторую, когда вторая настройка прошла флаг = 2, и по логике с нового включения устройства программа должна не заходить в функцию опроса, как это сделать не очень понимаю. вот говнокод: #include <mega16.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <delay.h> #include <alcd.h> #include <keyboard.h> #include <math.h> __eeprom int FZ, MR; int flag; char buf=0; char FZ_[5]; char MR_[4]; char buuf[4]={'1','2','3','4'}; char kek[4]; int i; int temp_FZ; /*int StrToInt(const char* snum) { int idx, strIdx = 0, accum = 0, numIsNeg = 0; const unsigned int NUMLEN = (int)strlen(snum); /* Check if negative number and flag it. */ if(snum[0] == 0x2d) numIsNeg = 1; for(idx = NUMLEN - 1; idx >= 0; idx--) { /* Only process numbers from 0 through 9. */ if(snum[strIdx] >= 0x30 && snum[strIdx] <= 0x39) accum += (snum[strIdx] - 0x30) * pow(10, idx); strIdx++; } /* Check flag to see if originally passed -ve number and convert result if so. */ if(!numIsNeg) return accum; else return accum * -1; } */ void main(void) { DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0); PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0); DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (0<<CS00); TCNT0=0x00; OCR0=0x00; TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10); TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; ASSR=0<<AS2; TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20); TCNT2=0x00; OCR2=0x00; TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (0<<TOIE0); MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00); MCUCSR=(0<<ISC2); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0); SFIOR=(0<<ACME); ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0); TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE); flag = 0; lcd_init(16); KEYB_Init(); while (1) { if(flag == 0) { for( i = 0; i<5; i++) { check_again: KEYB_ScanKeyboard(); buf = KEYB_GetKey(); if(buf == NULL) goto check_again; FZ_[i] = buf; lcd_gotoxy(0,1); lcd_putsf("FZ"); lcd_gotoxy(i,0); lcd_putchar(FZ_[i]); } flag=1; temp_FZ = atoi(FZ_); sprintf(kek,"%d", temp_FZ); delay_ms(5000); lcd_clear(); } lcd_gotoxy(0,0); lcd_puts(kek); /*for(i = 0; i<temp_FZ;i++) { temp_FZ = temp_FZ - i; itoa(temp_FZ, FZ_); delay_ms(1000); lcd_gotoxy(0,0); lcd_puts(FZ_); } // lcd_gotoxy(0,0); //lcd_puts(FZ_); */ } } Это то что ввел пользователь, ну ввел конечно же я)) а это, то что выдали эти функции преобразования.
×
×
  • Создать...