|
Простенькая программка измерения длительности импульса. |
|
|
|
Aug 31 2008, 17:46
|
Местный
  
Группа: Свой
Сообщений: 413
Регистрация: 15-12-06
Пользователь №: 23 563

|
Подпаял резистор, конденсатор ненашел. Все равно ресетится, но уже со значением MCUCSR=0x01, то есть бит, означающий что на ресет подан низкий уровень равен нулю. Вопрос: значит, ресет от помех все-таки был, сейчас помеха (0 на ресете) не вылазит - мне искать конденсатор? Проблема то вроде устранена. ПРо ватчдог я соврал - сейчас проверяю включен он или выключен. Так, если я правильно понял: Цитата Для того, чтобы включить сторожевой таймер, достаточно установить в 1 бит WDE -Watch Dog Enable. А вот выключить так просто не получится - и сделано это для защиты от тех же сбоев... Для выключения надо проделать следующие действия: Записать одновременно в WDE и WDTOE значения "1" В течение 4-х тактов процессора записать "0" в WDE. ТО выключить сторожевой таймер если он включен нужно так: WDTCR=0x18; WDTCR=0x10; Делаю это. Происходит ресет со значением WDTCR=0, MCUCSR=1; То же и без принудительного выключения. Кстати, почему вы решили что он включен - по умолчанию он ведь выключен. Что за бред.... BOD - если вы имеете ввиду фьюзы, то у меня BODEN=1. Далее..... Последовал совету: Цитата Следовательно, если в программе нужно определять режим сброса - то после анализа этих бит их просто нужно установить в "0". Тогда сброс по сторожевому таймеру можно будет определить по отсутствию "1" в вышеописанных битах. Сделал так: Код void main(void) {
//WDTCR=0x18; //WDTCR=0x10;
lcd_init(); backcolor=black; textcolor=yellow;
lcd_clr(); fill_screen(black);
lcd_setxy(20,20); lcd_str_fl("MCUCSR=",f8x14, textcolor); lcd_str_ram(MCUCSR,f8x14, textcolor); lcd_setxy(20,40); lcd_str_fl("WDTCR=",f8x14, textcolor); lcd_str_ram(WDTCR,f8x14, textcolor);
MCUCSR=0x00; delay_ms(3000); INT_ON; это включение прерывания, установлено черех #define
} В итоге на экран выводится WDTCR=0, MCUCSR=0; Получается что сброс по сторожевому таймеру? Убираю комментарии со строк WDTCR=0x18; WDTCR=0x10; (опять таки, если я правильно понял как отключить сторожа) - тот же эффект.
|
|
|
|
|
Aug 31 2008, 18:53
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(Зверюга @ Aug 31 2008, 20:46)  Получается что сброс по сторожевому таймеру? Убираю комментарии со строк WDTCR=0x18; WDTCR=0x10; (опять таки, если я правильно понял как отключить сторожа) - тот же эффект. детектор питания отключён, с ресетом Вы справились, правда это не защитит от наносекундных помех без хорошей земли (разводки) и конденсатора. Получается что сторожевой таймер у вас командовал парадом. Ну и начинайте уже заниматься основной задачей. Вот как я планирую сделать тахометр: Код //Chip type: ATmega8535 //Chip clock 14,745600Mh /******************************************************************************* * Тахометр четырёхтактного двигателя. Импульсы подаются с прерывателя. За один * оборот проходит два импульса. Для измерения частоты оборотов двигателя * исспользуется таймер один. Он запущен в свободном режиме счёта. Предделитель * тактовой выбран 64, т.о. тактовая таймера составляет 230,400 kHz. Для даного * таймера разрешено два прерывания: по завату по спаду импульса и по переполнению. * Для измерения периода следования входных импульсов с прерывателя исспользовано * прерывание режима захвата. Т.о. производится измерение полупериода (два импульса * за оборот). * В прерывании захвата производится копирование состояние счётчика на момент прерывания * из регистра захвата ICR1. Прерывание переполнение происходит каждые 0.25мс в котором * происзводится обновление информации выводимой на ЖКИ. ******************************************************************************* #include <inavr.h> #include <ioavr.h> #include <stdint.h> #include <stdlib.h> #define OborotiZaMinConst 6912000 /* Определение глобальных переменных*/ signed int CaptureTmp, CaptureOld; signed int PPeriod; div_t dtmp; char str_tmp[6];
// Timer 1 overflow interrupt service routine #pragma vector = TIMER1_OVF_vect __interrupt void Timer1_overflow(void) { //частное (quot) и остаток (rem) /*div_t typedef struct { int quot, rem; } div_t; */ char i; signed int OborotiZaMin; str_tmp[5] = 0; OborotiZaMin = (OborotiZaMinConst + (PPeriod >> 1)) / PPeriod;
dtmp = div(OborotiZaMin, 10); str_tmp[4] = dtmp.rem + '0'; dtmp = div(dtmp.quot, 10); str_tmp[3] = dtmp.rem + '0'; dtmp = div(dtmp.quot, 10); str_tmp[2] = dtmp.rem + '0'; dtmp = div(dtmp.quot, 10); str_tmp[1] = dtmp.rem + '0'; str_tmp[0] = dtmp.quot + '0'; // Гашение незначащих нулей for (i = 0; i < 4; ++i) if (str_tmp[i] == '0') str_tmp[i] = ' '; else break;
} // Timer 1 input capture interrupt service routine #pragma vector = TIMER1_CAPT_vect __interrupt void Timer1_input_capture(void) { CaptureTmp = ICR1; PPeriod = CaptureTmp - CaptureOld; CaptureOld = CaptureTmp; } void TimOneInit (void){ // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 230,400 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: On // Input Capture Interrupt: On // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x03; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; } int main( void ) { TimOneInit(); _enableinterupt(); for(;;){ }
} В общем, код ещё на стадии разработки, но Вам для маленького направления пойдёт.
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Aug 31 2008, 19:23
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(Зверюга @ Aug 31 2008, 22:06)  Я всего лишь добился что в MCUCSR второй бит стал равен нулю, то есть не было зафиксировано низкого уровня на ресете. Это уже хорошо. был - бы конденсатор было бы нелогично не зафиксировать низкий уровень. Поскольку вы могли и раньше включить его, или МК поддался воздействию помехи он мог сам включиться хотя это уже из ряда фантастики. теперь из ДШ выключение дога Код void WDT_off(void) { /* reset WDT */ _WDR(); /* Write logical one to WDTOE and WDE */ WDTCR |= (1<<WDTOE) | (1<<WDE); /* Turn off WDT */ WDTCR = 0x00; }
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Aug 31 2008, 19:39
|
Местный
  
Группа: Свой
Сообщений: 413
Регистрация: 15-12-06
Пользователь №: 23 563

|
ТАК, ПОХОЖЕ ГЛЮК ВСЕ ТАКИ СВЯЗАН С БИБЛИОТЕКОЙ ЖКИВывел содержимое регистров на диоды портов моей отладочной платы, расставил по ходу программы маячки, выяснилось - если инициализировать дисплей, очишать его экран, то все ОК, ресета нет. Если же пытаться вывести что-то на экран, и после этого включить прерывания - происходит РЕСЕТ. ОДНАКО, если после выведения на экран вызвать функцию библиотеки lcd_clr(), и после этого включить прерывание - РЕСЕТ не происходит. Если включать прерывания в самом начале основного цикла - то РЕСЕТ происходит при инициализации дисплея. Господа, мне остается только привести здесь текст библиотеки и попросить вас взглянуть, чего вне есть потенциально опасного в плане ресета, может конфликты какие? Код #include <spi.h> #include <delay.h> #include <stdio.h> #include <mega32.h> #include <fonts.c> #include <defines.c>
u08 buffer[1][5]; u08 posx,posy;
#define LCD_PORT PORTB // экран сидит на порте B #define LCD_DDR DDRB //
#define LCD_CS 2 // биты порта #define LCD_RESET 3 #define LCD_RS 4 #define LCD_MOSI 5 #define LCD_MISO 6 #define LCD_SCK 7
#define SPIF 7 #define SPI2X 0
#define SPR0 0 #define SPR1 1 #define SPHA 2 #define SPOL 3 #define MSTR 4 #define DORD 5 #define SPE 6 #define SPIE 7
#define DISP_W 132 #define DISP_H 176 #define CHAR_H 14 #define CHAR_W 8 #define TEXT_COL 16 #define TEXT_ROW 12
// INIT1:; 24bytes const ui16 INIT1[12]={0xFDFD,0xFDFD,0xEF00,0xEE04,0x1B04,0xFEFE,0xFEFE,0xEF90,0x4A04,0x7F3F,0xEE 04,0x4306};
//INIT2:; 40bytes const ui16 INIT2[20]={0xEF90,0x0983,0x0800,0x0BAF,0x0A00,0x0500,0x0600,0x0700,0xEF00,0xEE0C,0xEF 90,0x0080,0xEFB0,0x4902, 0xEF00,0x7F01,0xE181,0xE202,0xE276,0xE183};
//INIT3:; 2bytes const ui16 INIT3[1]={0x8001}; /* // INIT1:; 24bytes const u08 INIT1[24]={0xFD,0xFD,0xFD,0xFD,0xEF,0x00,0xEE,0x04,0x1B,0x04,0xFE,0xFE,0xFE,0xFE,0xEF ,0x90,0x4A,0x04,0x7F,0x3F,0xEE,0x04,0x43,0x06};
//INIT2:; 40bytes const u08 INIT2[40]={0xEF,0x90,0x09,0x83,0x08,0x00,0x0B,0xAF,0x0A,0x00,0x05,0x00,0x06,0x00,0x07 ,0x00,0xEF,0x00,0xEE,0x0C,0xEF,0x90,0x00,0x80,0xEF,0xB0,0x49,0x02, 0xEF,0x00,0x7F,0x01,0xE1,0x81,0xE2,0x02,0xE2,0x76,0xE1,0x83};
//INIT3:; 2bytes const u08 INIT3[2]={0x80,0x01}; */
//===========================================port_init============================ ==============================
void port_init(void) { // setup serial data I/O pins
LCD_PORT.LCD_RESET=0; // reset display LCD_DDR.LCD_RESET=1; // set reset as output
LCD_DDR.LCD_MOSI=1; // MOSI must be set as output for SPI LCD_PORT.LCD_MOSI=1; // MOSI must be set as output for SPI LCD_PORT.LCD_CS=0; // deselect display LCD_DDR.LCD_CS=1; // SS must be output for Master mode to work
LCD_PORT.LCD_SCK =0; // set SCK low LCD_DDR.LCD_SCK=1; // set SCK as output LCD_PORT.LCD_MISO=1; // enable pull up of MISO to avoid floating input
LCD_PORT.LCD_RS=1; // RS=high LCD_DDR.LCD_RS=1; // RS is output SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0); SPSR = (1<<SPI2X); delay_ms(4); // wait one ms to have a nice reset LCD_PORT.LCD_RESET=1; // release reset }
//******************************************************************************** ******************
void lcd_wrcmd16(ui16 dat) { lcd_wrcmd((dat>>8)); lcd_wrcmd(dat); } //******************************************************************************** ****************** void lcd_wrdat16(ui16 dat) { lcd_wrdata(dat>>8); lcd_wrdata(dat); } //******************************************************************************** ******************
void fill_screen(ui16 color) { ui16 i=0; lcd_wrcmd16(0xEF90); lcd_wrcmd16(0x0500); lcd_wrcmd16(0x0600); lcd_wrcmd16(0x0700); for (i=0; i<DISP_W*DISP_H; i++)lcd_wrdat16(color); } //******************************************************************************** ******************
void lcd_wrcmd(u08 dat) { LCD_PORT.LCD_CS=0; LCD_PORT.LCD_RS=1; spi_send(dat); } //******************************************************************************** ******************
void lcd_wrdata(u08 dat) {
LCD_PORT.LCD_CS=0; LCD_PORT.LCD_RS=0; spi_send(dat); }
//******************************************************************************** ******************
void spi_send(u08 dat) {
#asm
ld r26,y sbi 0xd,7 out 0xf,r26 SPI_SEND_2: sbis 0xe,7 rjmp SPI_SEND_2 sbi 0x18,2 #endasm
}
//******************************************************************************** ******************
void spi_send0(u08 dat) { spi_send(dat); spi_send(0x00); }
//******************************************************************************** ******************
void lcd_cspulse(void) { LCD_PORT.LCD_CS = 1; #asm("nop"); LCD_PORT.LCD_CS = 0; }
//******************************************************************************** ******************
void lcd_init(void) { ui16 i=0;
LCD_PORT.LCD_CS=1; LCD_DDR.LCD_CS=1; port_init();
LCD_PORT.LCD_CS=0; delay_ms(4); LCD_PORT.LCD_RS=1; for (i=0;i<12;i++) lcd_wrcmd16(INIT1[i]); delay_ms(7); for (i=0;i<20;i++) lcd_wrcmd16(INIT2[i]); delay_ms(50);
for (i=0;i<1;i++) lcd_wrcmd16(INIT3[i]); delay_ms(5);
lcd_clr(); LCD_PORT.LCD_CS=1; }
//******************************************CHAR********************************** *****************
void put_char(char c,u08 font,ui16 color) { u08 h,ch,p,mask,font_height,font_width; char i, j; ui16 b; u08 rot=0; if(font==f8x14) { font_height=14; font_width=8; lcd_wrcmd16(0xEF90); lcd_wrcmd16(0x0504); lcd_wrcmd16(0x0800+posy); lcd_wrcmd16(0x0A00+posx); lcd_wrcmd16(0x0900+posy+font_height-1); lcd_wrcmd16(0x0B00+posx+font_width-1); for (h=0; h<font_height; h++) // every column of the character { ch=font8x14[ c-32 ][font_height-h-1]; // mask=0x80; for (p=0; p<font_width; p++) // write the pixels { if (ch&mask) { lcd_wrdat16(textcolor); } else { lcd_wrdat16(backcolor); } mask=mask/2; } } } if(font==f8x8) { font_height=8; font_width=8; lcd_wrcmd16(0xEF90); lcd_wrcmd16(0x0500); lcd_wrcmd16(0x0800+posy); lcd_wrcmd16(0x0A00+posx); lcd_wrcmd16(0x0900+posy+font_height-1); lcd_wrcmd16(0x0B00+posx+font_width-1); for (h=0; h<font_height; h++) // every column of the character { ch=font8x8[ c-32 ][h]; mask=0x80; for (p=0; p<font_width; p++) // write the pixels { if (ch&mask) { lcd_wrdat16(textcolor); } else { lcd_wrdat16(backcolor); } mask=mask/2; } } } posx = posx + font_width; }
//******************************************************************************** ******************
void lcd_setxy(u08 x, u08 y) { posx=x; posy=y;
//lcd_wrcmd16(0x0504); //lcd_wrcmd16(0x0800+x); //lcd_wrcmd16(0x0A00+y); //lcd_wrcmd16(0x0900+x+8-1); //lcd_wrcmd16(0x0B00+y+14-1); } //******************************************************************************** ******************
void lcd_clr(void) { #asm push r30 push r31
ldi r24,0xEF rcall lcd_wrcmd ldi r24,0x90 rcall lcd_wrcmd ldi r24,0x05 rcall lcd_wrcmd ldi r24,0x00 rcall lcd_wrcmd ldi r24,0x08 rcall lcd_wrcmd ldi r24,0x00 rcall lcd_wrcmd ldi r24,0x0A rcall lcd_wrcmd ldi r24,0x00 rcall lcd_wrcmd ldi r24,0x09 rcall lcd_wrcmd ldi r24,0x84 rcall lcd_wrcmd ldi r24,0x0B rcall lcd_wrcmd ldi r24,0xB0 rcall lcd_wrcmd
ldi r31, 0xB6 ldi r30, 0xB1 ldi r24, 0xFF LCD_CLEAR_1: rcall lcd_wrdata sbiw r30,1 brne LCD_CLEAR_1 pop r31 pop r30 ret lcd_wrcmd: cbi 0x18,2 sbi 0x18,4 rjmp SPI_SEND lcd_wrdata: cbi 0x18,2 cbi 0x18,4 SPI_SEND: sbi 0xd,7 out 0xf,r24 SPI_SEND_0: sbis 0xe,7 rjmp SPI_SEND_0 in r0,0xf sbi 0x18,2 ret #endasm }
//**********************************рисуем пиксели в коорд. x и y цветом color****************************************************************
void lcd_pset(u08 x , u08 y , ui16 color) { lcd_wrcmd16(0xEF90); lcd_wrcmd16(0x0504); lcd_wrcmd16(0x0800+y); lcd_wrcmd16(0x0A00+x); lcd_wrdat16(color);
} //******************************************************************************** ****************** void lcd_circ(u08 xcenter, u08 ycenter, u08 rad, ui16 color) { si16 tswitch,y1,x1 = 0; u08 d;
d = ycenter - xcenter; y1 = rad; tswitch = 3 - 2 * rad; while (x1 <= y1) { lcd_pset(xcenter + x1, ycenter + y1, color); lcd_pset(xcenter + x1, ycenter - y1, color); lcd_pset(xcenter - x1, ycenter + y1, color); lcd_pset(xcenter - x1, ycenter - y1, color); lcd_pset(ycenter + y1 - d, ycenter + x1, color); lcd_pset(ycenter + y1 - d, ycenter - x1, color); lcd_pset(ycenter - y1 - d, ycenter + x1, color); lcd_pset(ycenter - y1 - d, ycenter - x1, color);
if (tswitch < 0) tswitch += (4 * x1 + 6); else { tswitch += (4 * (x1 - y1) + 10); y1--; } x1++; } }
//******************************************************************************** ****************** void lcd_line(u08 x1,u08 y1,u08 x2,u08 y2,ui16 color) {
si16 x,y,d,dx,dy,i,i1,i2,kx,ky; s08 flag;
dx = x2 - x1; dy = y2 - y1; if (dx == 0 && dy == 0) lcd_pset(x1, y1, color); else { kx = 1; ky = 1; if( dx < 0 ) { dx = -dx; kx = -1; } else if(dx == 0) kx = 0; if(dy < 0) { dy = -dy; ky = -1; } if(dx < dy) { flag = 0; d = dx; dx = dy; dy = d; } else flag = 1; i1 = dy + dy; d = i1 - dx; i2 = d - dx; x = x1; y = y1;
for(i=0; i < dx; i++) { lcd_pset(x, y, color); if(flag) x += kx; else y += ky; if( d < 0 ) d += i1; else { d += i2; if(flag) y += ky; else x += kx; } } lcd_pset(x, y, color); } }
//******************************************************* Прямоугольник ******************************* void lcd_rect(u08 x, u08 y, u08 x1, u08 y1,ui16 color) { lcd_line (x,y,x,y1,color); lcd_line (x,y,x1,y,color); lcd_line (x,y1,x1,y1,color); lcd_line (x1,y,x1,y1,color); }
//******************************************************* Pакрашенный прямоугольник ***************************** void lcd_fillrect(u08 x, u08 y, u08 x1, u08 y1,ui16 color) { u08 i; for (i=y; i<=y1; i++) lcd_line(x,i,x1,i,color); }
//******************************************************вывод строка из flash****************************** void lcd_str_fl(u08 flash*str,u08 font,ui16 color) { while ( *str !='\0') { put_char(*str++,font,color); } } //********************** void ram_to_lcd(unsigned char*str,u08 font,ui16 color) { while (*str !='\0') { put_char(*str++,font,color); } } //******************************************************вывод строка из ram****************************** void lcd_str_ram(ui16 var, u08 font,ui16 color) { sprintf(buffer ,"%-u",var); ram_to_lcd(buffer,font,color); } //******************************************************вывод картинки********************************** Цитата void WDT_off(void) { /* reset WDT */ _WDR(); /* Write logical one to WDTOE and WDE */ WDTCR |= (1<<WDTOE) | (1<<WDE); /* Turn off WDT */ WDTCR = 0x00; } CodeVision это не проглотит. Переделывать не собираюсь, чтобы не гадать потом - само по себе не сработало или коряво переделал. Если знаете как это написать в CodeVision, например чем заменить _WDR(); , напишите.
|
|
|
|
|
Aug 31 2008, 21:16
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Зверюга @ Sep 1 2008, 01:39)  Господа, мне остается только привести здесь текст библиотеки Столь большие по объему исходники вообще-то в виде аттачей прикладывать принято. Цитата(Зверюга @ Sep 1 2008, 01:39)  и попросить вас взглянуть, чего вне есть потенциально опасного в плане ресета, может конфликты какие? Цитата //******************************************************вывод строка из ram****************************** void lcd_str_ram(ui16 var, u08 font,ui16 color) { sprintf(buffer ,"%-u",var); ram_to_lcd(buffer,font,color); } Наивероятная причина выделена. Возможные последствия применения sprintf - наползание стека на данные.
|
|
|
|
|
Sep 1 2008, 03:17
|
Местный
  
Группа: Свой
Сообщений: 413
Регистрация: 15-12-06
Пользователь №: 23 563

|
Вы не правы. Это наименее вероятная причина. Функция lcd_pset так же вызывает ресет, а она не подразумевает вызов sprintf. Комментированием строк в библиотеку мной установлено, что если в во всех функциях закомментировать вызов функции spi_send() то ресет не происходит. То есть причина в этой функции. Код void spi_send(u08 dat) {
#asm
ld r26,y sbi 0xd,7 out 0xf,r26 SPI_SEND_2: sbis 0xe,7 rjmp SPI_SEND_2 sbi 0x18,2 #endasm
} Ваши предложения?
|
|
|
|
|
Sep 1 2008, 17:23
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(Зверюга @ Aug 31 2008, 22:39)  CodeVision это не проглотит. Переделывать не собираюсь, чтобы не гадать потом - само по себе не сработало или коряво переделал. Если знаете как это написать в CodeVision, например чем заменить _WDR(); , напишите. Это простая асмовская команда WDR(Watchdog Reset). и ещё, трудно сказать, а без прерываний выводится ведь на ура? Посмотрите ассемблерный листинг сгенерированный компилятором - может там чтото заметите. и ещё, в разделе для АВР люди пользуются дисплеями от сименса (тема есть такая, довольно популярная), может стоит там спросить?
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Sep 2 2008, 05:20
|
Местный
  
Группа: Свой
Сообщений: 413
Регистрация: 15-12-06
Пользователь №: 23 563

|
Цитата замените для чистоты эксперимента функцию на асме - на сишный эквивалент, тем более компилятор вам сгенерит код ничуть не хуже... Я "консерваториев не заканчивал", не могли бы вы выразить свою мысль в Сишном коде?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|