Вы не вошли.
Пробовал подключать внешний резонатор 8.000 МГц и пробовал без него - МК не читается :-(
Я пользовался программой spiwc.exe, она как-то очень хитро принимает значения Fuse bits для записи -
2х значное число в Hex, потом меняет цифры местми, инвертирует их и тогда записывает 8 бит в МК.
Может я не совсем прав насчет параметров spiwc.exe, но я запутался основательно :-(
Похоже в МК записались совсем не те значения, которые я хотел.
Ну а посмотреть их я уже не могу.
Если кто знает, подскажите пожалуйста значения всех Fuse bits для использования внешнего резонатора с частотой 8 ... 16 Мгц.
Попробую отдать МК чтобы его перешили параллельным программатором, но вот что записать в fuse bits не уверен.
Спасибо.
Вне форума
Попробуйте подать на вывод XTAL1 внешнюю тактовую частоту.
Вне форума
что записать в fuse bits не уверен.
Спасибо.
Почитайте внимательно - winavr.nm.ru/07.htm - там подробно все расписано.
Вне форума
Большое спасибо ;-)
Хороший мануал, - буду разбираться.
Вне форума
Все, с этой проблемой я разобрался - мне перешили фьюзы на значения по-умолчанию параллельным программатором и все заработало
Но когда я писал программу, столкнулся с такой проблемой:
при использовании мультиплексированных (надеюсь это так называется) семисегментных индикаторов приходится переключать питание на каждую цифру, затем выводить необходимый символ, удерживать его несколько милисекунд, потом тушить цифру на несколько милисекунд и так для всех знаков. Эта процедура занимает довольно много времени, втечении которого МК ничего кроме этого не делает. А для неприрывного отображения значений приходится помещать все это дело в цикл.
В ходе нескольких экспериментов я написал вот такой код:
void displaySign(int value){
if(value==0){
PORTA=0b00011000;
return;
}
if(value==1){
PORTA=0b01111011;
return;
}
if(value==2){
PORTA=0b00101100;
return;
}
if(value==3){
PORTA=0b00101001;
return;
}
if(value==4){
PORTA=0b01001011;
return;
}
if(value==5){
PORTA=0b10001001;
return;
}
if(value==6){
PORTA=0b10001000;
return;
}
if(value==7){
PORTA=0b00111011;
return;
}
if(value==8){
PORTA=0b00001000;
return;
}
if(value==9){
PORTA=0b00001001;
return;
}
}
void display(int value){
PORTB=0b11001111;
displaySign(value/100);
delay_ms(1);
PORTA=255;
delay_ms(1);
PORTB=0b10101111;
displaySign((value%100)/10);
delay_ms(1);
PORTA=255;
delay_ms(1);
PORTB=0b10011111;
displaySign(value%10);
delay_ms(1);
PORTA=255;
delay_ms(1);
}
....
for(i=0; i<1000; i++){
for(j=0; j<20; j++) display(i);
}
....
Все работает отлично, но получается что МК постоянно занят выводом значений.
Каким образом можно реализовать нормальный вывод?
Можно ли как-нибудь запустить его в отдельном потоке? (шутка )
Подскажите пожалуйста.
Вне форума
Динамическую индикацию нужно делать по прерываниям таймера. Настраиваете таймер так, чтобы он генерировал прерывания каждую миллисекунду. Это можно сделать так: к примеру, для mega8 взять таймер 2, установить ему режим CTC (Clear Timer on Compare), загрузить регистр сравнения нужным числом, разрешить прерывания по совпадению и написать обработчик прерываний.
#define FCLK 10.000 //частота кварца, Мгц
#define SYS_TM 1000.0 //период системного таймера, мкс
#define T2VAL (FCLK * SYS_TM / 64.0) //загрузочная величина таймера 2
TCCR2 = (1<<WGM21) | (1<<CS22); //режим таймера 2: CTC, CK/64
OCR2 = T2VAL - 1; //загрузка регистра сравнения
TIFR = (1 << OCIE2); //сброс отложенных прерываний
TIMSK = (1 << OCIE2); //разрешение прерывания по совпадению
__enable_interrupt(); //разрешение прерываний
В обработчике вызывать SetSeg() для каждой из цифр по очереди. Для этого потребуется переменная Phase, которая будет говорить, какую цифру в данный момент индицируем.
#pragma vector = TIMER2_COMP_vect
__interrupt void Timer(void)
{
static char Phase;
Port_SCAN1_1; //выключение всех разрядов дисплея
Port_SCAN2_1;
Port_SCAN3_1;
Port_SCAN4_1;
switch(Phase) //проверка текущей фазы
{
case 0:
SetSeg(SegData[0]); //вывод сегментов разряда 1
Port_SCAN1_0; //включение разряда 1
break;
case 1:
SetSeg(SegData[1]); //вывод сегментов разряда 2
Port_SCAN2_0; //включение разряда 2
break;
case 2:
SetSeg(SegData[2]); //вывод сегментов разряда 3
Port_SCAN3_0; //включение разряда 3
break;
case 3:
SetSeg(SegData[3]); //вывод сегментов разряда 4
Port_SCAN4_0; //включение разряда 4
break;
}
if(Phase < 3) Phase++; else Phase = 0; //следующая фаза
}
Ну и число Value нужно разложить на декады заранее и сохранить в массиве SegData[], а не делать деление на каждом цикле индикации. Лучше в массиве вообще хранить копию сегментов индикатора, чтобы каждый раз не перекодировать в 7-сегментный код. А в основной программе, когда требуется что-то вывести на индикатор, вызываается функция Display(Value), которая просто заполняет массив SegData[], разложив Value на тетрады и перекодировав в семисегментный код. Всё.
Я бы мог полностью привести исходный текст программы, но пользы от этого, думаю, будет ноль. Лучше пишите сами, постите сюда исходник, будем править.
Отредактировано Liv (18.03.2007 14:11:47)
Вне форума
Большое спасибо за помощь и замечания буду разбираться
Вне форума
С прерываниями вроде разобрался
Для примера решил сделать таймер обратного отсчета, поместил функцию, зависящую от времени, в функцию обработки таймера, а в main(){} поместил функцию вывода на табло. Вроде все работает, но тут есть две непонятности:
Уход времени на пяти минутах составил ~6 секунд - это из-за внутреннего генератора на 1 МГЦ? Какая будет точность с внешним резонатором?
И еще я чего-то не понял с настройками частоты таймера, перебрал все делители из DataSheet, но максимальная частота оказалась 3,906 КГц.
int time=0;
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
time++;
if(time==3906){
displayValue++;
time = 0;
}
}
void main(void)
{
PORTA=0x00;
DDRA=0xFF;
PORTB=0x00;
DDRB=0xF0;
TCCR0=0x00;
TCNT0=0x00;
PLLCSR=0x00;
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK=0x04;
USICR=0x00;
ACSR=0x80;
#asm("sei")
while (1)
{
display(displayValue);
};
}
Вне форума
Уход времени на пяти минутах составил ~6 секунд - это из-за внутреннего генератора на 1 МГЦ? Какая будет точность с внешним резонатором?
Возможно. Для внутреннего RC-генератора уход на 2% - обычное дело. С внешним кварцевым резонатором точность будет значительно лучше. Конкретное значение зависит от примененного резонатора.
И еще я чего-то не понял с настройками частоты таймера, перебрал все делители из DataSheet, но максимальная частота оказалась 3,906 КГц.
Всё верно. Вы используете прерывание по переполнению, таймер 8-разрядный, 1 МГц / 256 = 3.90625 КГц.
Вне форума
Прошу прощения за бестактный вопрос
А какие еще прерывания по таймеру я могу использовать чтобы отмерять более короткие промежутки времени?
Я хочу сделать хронограф - прибор для измерения скорости полета пули, устройство преддельно простое: 2 оптических датчика в трубке. Для получения высокой точности при малом удалении датчиков друг от друга, мне нужно измерять время до микроСекунд. Каким образом мне можно реализовать такое измерение времени?
Отредактировано Xumuk (21.03.2007 12:06:07)
Вне форума
[ Сгенерировано за 0.046 сек, 7 запросов выполнено - Использовано памяти: 628.8 Кбайт (Пик: 679.16 Кбайт) ]