Вячеслав_НС

помогите с кодом на С для Atm8

27 сообщений в этой теме

Здравия всем ! 

Пожалуйста помогите разобраться . Пытаюсь написать прошивку для Atmega8 на С в Atmel Studio 7.0 . 

Программка простая ( небольшая ) ... по сути - частотомер ( только для небольшого диапазона частот ... примерно - от нескольких Гц , до нескольких десятков кГц ) .

Импульсы считать со входа T0 ( PD4 )  ...микр-ра Atmega8a ( 28 pin ) . Использовать TCNT1 (16 bit) . Полученное число выводить на Lcd - nokia5110 .

Как я понимаю прерывания не нужны , алгоритм простой :

1) инициализация дисплея и счетчика 

2) остановить (запретить счет) счетчик AVR -  ( CS12,CS11,CS10-прописать нули )

3) обнулить ( отчистить) буфер дисплея и счетчика ( AVR )

3) запустить бесконечный цикл :

                                                                а) разрешить считать импульсы с  T0 ( PD4 )  - ( CS12,CS11,CS10-прописать единицы )

                                                                б) задать паузу  (  надеюсь правильно рассчитал - 10 мсек )

                                                                в)  запретить считать - ( CS12,CS11,CS10-прописать нули )

                                                                г) вывести полученное значение со счетчика на дисплей 

 

 

( СИЛЬНО НЕ СМЕЙТЕСЬ ... Я НАЧИНАЮЩИЙ . с АЦП AVR разобрался удачно , собрал схемку в протеусе , написал прошивку , спаял ... все работает . а вот с таймером завис надолго . есть много примеров в инете , но все слишком навороченные для меня . запутался . )

вот примерно что получилось с таймером ... упрощал как мог ...в общим не получается . подскажите где косяк .(только просьба - без лишних наворотов и по возможности с комментариями ... задача - не повторить чужую программу ... а разобраться самому )

//Atmega8A

#define  F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "n5110.h"

void presets(){
    Lcd_init();
    Lcd_clear();
    TCCR1B =0x00;
    TCNT1=0000;

     TCCR0 |= (1 << CS01); 
  }

int main(void)
{
    presets();
    while (1) 
    {

     TCNT1=0000;
    TCCR1B|=(1<<CS12)|(1<<CS11)|(1<<CS10);
    _delay_ms(10);
    TCCR1B &=~(1<<CS12)|(1<<CS11)|(1<<CS10);
        
    Lcd_prints(5,2,FONT_1X,(TCNT1)PSTR("Hz"));    //                                                КОМПИЛЯТОР РУГАЕТСЯ НА ЭТУ СТРОЧКУ 
    Lcd_update();
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    577
3 часа назад, Вячеслав_НС сказал:

а вот с таймером завис надолго

 

3 часа назад, Вячеслав_НС сказал:

КОМПИЛЯТОР РУГАЕТСЯ НА ЭТУ СТРОЧКУ 

А причём тут таймер, если он ругается на строчку Lcd_prints ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

не понимаю как правильно вывести показания таймера(счетчика) на LCD  .  если написать так ... Lcd_prints(10,2,FONT_1X,( unsigned char ) PSTR("Hz"));    то программа воспринимает без ошибок . вот я и прошу...пожалуйста подскажите некоторые моменты в написании программки . в частности - как оформить вывод на экран значение из счетчика TCNT1 в бесконечном  цикле . учусь по готовым примерам . с АЦП сам разобрался , с таймерами засел . не все понимаю . нужен простой пример .очень простой . либо подсказка . за ранее благодарен .

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Впервые на русском языке! Работаем с микроконтроллерами STM32F7(на основе STM32F7 Online Training)

Цикл материалов на основе STM32F7 Online Training от компании STMicroelectronics. Описаны функциональные блоки и инструменты разработки для семейства микроконтроллеров STM32F7, охватывающие тематику системной периферии, памяти, безопасности, аналоговой периферии, цифровой периферии, таймеров, экосистемы.

Подробнее>>

как всегда , простые вещи упускаю из виду ... не "Lcd_prints " надо было использовать , а "Lcd_printf ". Прошу прощения . похоже тему зря создал . пока ковырялся в сложном , допустил простую ошибку . Простите мужики , лоханулся . да и подходящий пример для себя уже нашел в инете . но все равно - спасибо . 

вообще я хотел написать прошивку не совсем для частотомера . там нужно подставить формулу (F = 0,48/(R1×C1) расчета емкости по частоте ( генератор на обычной k561лн2 . из двух элементов . резистор на 350 кОм и собственно - измеряемая емкость ) . получается измеритель емкости .просто есть куча плат с СМД детальками .сопрухи подписаны , емкости -нет .думаю измерение в пределах ~ 20 pF - 800nF мне хватит . подходящий пример прошивки нашел . формулу вставил . все работает .погрешность не большая . единственное , там используется двухстрочный дисплей 1602 , а не нокиа-5110 .

генератор.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
солар    186
7 часов назад, Вячеслав_НС сказал:

погрешность не большая

С чем сравнивали? За эталон что брали?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

поправка ,  я имел ввиду - небольшое расхождение с номиналом на проверочной емкости , а не погрешность ( моя схемка ни в коем случае не претендует на калибровочное профессиональное оборудование ). я только начал осваивать СИ и МК  . к слову - не всегда удается запустить МК от внешнего кварца , как и в данном случае . так что точность измерения емкости , конечно не высокая . проверял разными емкостями - от 27pF до 680nF . на емкости 91pF показания - 91 pF !!!

если не ошибаюсь , этот тип емкости довольно точный и термостабильный (4я с лева ).

 

другое дело - схема с использованием АЦП , там измерение не завязано на частоту ( при работе АЦП до 200кГц ). получилась вполне приемлемая точность измерения . шкала измерения от - 10.5 кПа до + 10.5 кПа ... калибровал свою схемку по цифровому манометру ( у него погрешность y±0.005%) расхождение в показаниях начинается на сотых долях кПа (0.0х).

емкости.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если кому то интересно ... решил проблему с запуском atmega8 от внешнего кварца ( в частности 8 Мгц ) , я просто убрал нагрузочные емкости . по схеме  - 22pF . более опытные люди подсказали - в МК могут присутствовать свои , внутренние ( подтягиваются настройками фьюзов ). 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

добрый день. дабы не плодить темы задам вопрос здесь. начну с начала дабы было понятно сначала... купил плату управления чпу (а подумать не купил)через лпт и драйверы шаговых биполярных двигателей на L298N (но они по сути просто усилители). так вот чтобы плата управления могла работать с драйвером нужен контроллер этих самых двигателей. плата управления step/dir (шаг/реверс). на картинке показано что должно происходить. только нужно уточнить что если на входе остановилась единица то и на выходе она тоже должна быть. кусок кода для переборки ногами я накидал но вот только от кнопки (на входе один сигнал). короче хочу наводящий ответ как это сделать.

unsigned char i;
      while (1) 
    {
        if (PINC&(1<<5))
        {
            for (i=0;i<=3;i++)
        {
            PORTD=(1<<i);
            _delay_ms(20);            
        }
        }
        else
        {
            PORTD=0;
        }
    }

20181215_133122.jpg

ах да атмега8 микроконтроллер, пишу на С++

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
snn_krs    48

Была такая проблема. Решил проще купил три драйвера на А4988, они тянут до 2-х ампер ( на али стоит от 50 руб. ). Если нужен больший ток, можно поставить на выходы ключи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
_abk_    100
4 часа назад, Дмитрий Вас сказал:

хочу наводящий ответ как это сделать

В поиске найдете кучу таких контроллеров на любой вкус, в том числе и с исходниками. А L297  чем не подходит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

L297 нужно заказывать и ждать пару месяцев, а атмега 8 лежит на столе. да и на мк компактней, ее одной хватит на все три оси.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 454
7 часов назад, Дмитрий Вас сказал:

кусок кода для переборки ногами я накидал но вот только от кнопки (на входе один сигнал)

ерунда какая написано...

фиксируешь фронт импульса  на  тактовом входе , поймал фронт импульса, если направление ввперед  инкремент счетчика 0..7 , если назад декремент счетчика, в зависимости от значения счетчика выставляешь нужную комбинацию на выходе

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
void INTinit()
{
	GICR=((1<<INT0)|(1<<INT1)); //разрешаем прерывание int0 и int1
	MCUCR=((1<<ISC00)|(1<<ISC01)|(1<<ISC10)|(1<<ISC11));// прерывание по переднему фронту импульса int0 и int1
}
ISR(INT0_vect)
{
	PORTB=0b00001000>>1;
}

на каждое внешнее прерывание единица должна уходить вправо. подскажите в чем ошибка

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 454
3 минуты назад, Дмитрий Мамедиев сказал:

на каждое внешнее прерывание единица должна уходить вправо

с какого перепугу? вы тупо в порт пишите 0b00000100

сдвигают

PORTB>>=1;

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 25.12.2018 в 22:17, DrobyshevAlex сказал:

ISR() {
  // если прошлый шаг был 4 то сдвигаем обратно на 0 бит
  if (PORTD & 0b00001000) {
      PORTD = (PORTD & 0x0f) >> 3;
  } else { // если не 4 шаг то двигаем влево
      PORTD = (PORTD << 1) & 0x0F;
  }
}

 

Вы не видите разницу между тем что я показал как пример и тем что вы написали?

18 минут назад, Дмитрий Мамедиев сказал:

PORTB=0b00001000>>1;

 

PORTB=PORTB>>1; или  PORTB >>= 1;

 

Если вас пугают 0x0f & PORTB то можете упростить как то так

ISR(INT0_vect)
{
	if ((PORTB >>= 1) == 0) {
		PORTB = 0x00001000;
	}
}

Но я бы сделал так, на случай если порты PB5+ заняты чем то другим

ISR(INT0_vect)
{
	PORTB = (PORTB & 0xf0) | (PORTB & 0x0f) >> 1;
	if ((PORTB & 0x0f) == 0) {
		PORTB |= 1 << PB3;
	}
}

 

Изменено пользователем DrobyshevAlex

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
23 минуты назад, Дмитрий Мамедиев сказал:

должна уходить вправо

a >> b -  биты a сдвигаются на b позиций вправо как и при любой другой бинарной операции типа a + b не a изменится а просто вернется значение которое куда то надо записать

A = 2 + 1;
// тут A == 3
A = 2 + 1;
// тут по вашему A равно 4? или все же 3?

A = 0b00001000 >> 1;
// тут A равно 0b00000100;
A = 0b00001000 >> 1;
// если по вашему тут A будет 3 тогда почему должно быть 0b00000010??
// а если по вашему в 4 строке A должно быть равно 4 то вам нужно подтянуть математику школьный курс :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    644

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах



Если же инкрементировать счетчик и использовать его как индекс к массиву
с новым годом! А можно по подробней на этом месте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 минуты назад, Дмитрий Мамедиев сказал:

А можно по подробней на этом месте.

Вы программирование вообще не учили?)

//тип_массива имя_массива[количесво элементов] = { ... };
// например
uint8_t pins[4] = { 1, 4, 2, 0 };

Создайте массив с номерами пинов, и создайте массив с указателями на порты в которых эти пины.

Или же вообще структуру где будет описана ножка, я вам уже кидал набросок тут

В массиве будет что то типа

// сколько кнопок
#define BTN_COUNT 4

// массив кнопок
Button buttons[BTN_COUNT];

// счетчик
uint8_t pos = 0;

ISR () {
	bunnots[pos].метод(); // вызываете метод который вам нужен и как вы его обозвали, press() click() toggle() etc...
	if (++pos == BTN_COUNT) {
		pos = 0;
	}
}

 

Можете просто структуру из двух элементов сделать порт + пин что то типа

typedef struct {
	uint8_t pin;
	volatile uint8_t* port;
} pin_t;

pin_t pins[BTN_COUNT];

...

// натсроить порт и пин в массиве
pins[pos].port = &PORTB;
pins[pos].pin = PB0;

...

*(pins[pos].port) |= 1 << pins[pos].pin; // установить 1 на ноге

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вообщем повторюсь) Это не относится к МК атмега8 или стм32 или Intel core I-7. Это просто Вам нужно программирование учить. Основы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    644

Ну, пока вы на программы будете смотреть как на строчки текста с непонятными словами то так и будет. А слова, символы - это всего лишь выражение модели программы на понятном языке как человеку так и компьютеру. Думать нужно не словами а моделями, слова лишь для выражения этих моделей с головы.

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

Изменено пользователем Alexeyslav

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: Fcbb
      Как к схеме подключить батарею для питания схемы и usb разъём для зарядки батареи , а так же была возможность связи с пк через usb. И пожалуйста нарисуйте это на схеме что бы было видно как все подключено Схема
    • Автор: Григорий101
      Здравствуйте  , я хотел прошить AVR программатором STK500 . Но оказалось , чтобы  Bascom IDE прошивать им , необходим STK500.exe . Пожалуйста посмотрите , не лежит ли он где-нибудь у вас . Заранее спасибо
    • Автор: mazzi
      Повторил схему опубликованную на сайте паяльник. http://forum.cxem.net/index.php?/blogs/entry/548-повторил-схему-клона-avr-jtag-ice/&do=getLastComment
      Схема заработала, но так и не смог её заставить работать из под CVAVR, заводится только из под Atmel Studio 4.
      Может быть кому ни будь удалось это сделать? Если да, то подскажите, как этого достичь?
       
    • Автор: LettonDarkCat
      Купил USBASP программатор с aliexpress. На нем стояла старая прошивка, т.к в khazama при прошивке выдавало ошибки но микроконтроллер прошивался и память считывалась (короче просто старая прошивка на нем). Потом решил перепрошить программатор через arduino. Прошивка успешно закачалась, но теперь программатор вообще отказывается работать. Кто сталкивался, помогите.
    • Автор: Andrey Gressikov
      Я начинающий программист, пытаюсь программировать микроконтроллеры в среде АВР.
      У меня возник вопрос, вот например у нас есть двоичная система исчисления где 3 мы можем записать так:
      00000011, однако чтобы подать логическую 1 на третий порт микроконтроллера мы должны сделать следующую запись
      PORTC=00000100, т е существует некая разница между названиями портов и системами исчисления, в таком случае как мне используя 16 ричную систему исчисления подать напряжение на какую либо ногу порта.Я знаю что данная запись 0х01 подает логическую 1 на 0 ногу, а данная запись 0х10 на 4 ногу ,ну а как быть дальше?
      Как подать напряжение на 5 ногу порта? Если я в чем то заблуждаюсь - поправьте, если чего то незнаю расскажите.
      Заранее благодарю.