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

Помогите новичку написать код на си для Avr


Dimas19904

Рекомендуемые сообщения

Пару месяцев учюсь программированию на языке Си для AVR.

Использую компилятор Code Vision AVR и мк ATmega8.

Хотел составить программу частотомера для мк ATmega8.

Немогу понять как напиисать участок программы отвечающий за динамическую индикацию.

Индикатор использую АЛС318

Напишите или помогите написать программу динамической индикации на Си для ATmega8.

Изменено пользователем Dimas19904
Ссылка на комментарий
Поделиться на другие сайты

1. кодируем символы, которые должны выводиться.

у меня на порте сегменты a..h соответствуют выводам порта 0..7. так удобней программировать, но не очень иногда разводку платы делать. не страшно :)

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

То, что должно быть на индикаторе, удобно занести в массив, где каждый элемент соответствует одному разряду. Главное будет, правильно выполнить разбиение числа на цифры (в нужном порядке), но это легко.

73 de R9FDJ ex. UB8FCG | QTH LO88AA, PM-03, Пермь | RCWC #1256

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

1. кодируем символы, которые должны выводиться.

у меня на порте сегменты a..h соответствуют выводам порта 0..7. так удобней программировать, но не очень иногда разводку платы делать. не страшно :)

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

То, что должно быть на индикаторе, удобно занести в массив, где каждый элемент соответствует одному разряду. Главное будет, правильно выполнить разбиение числа на цифры (в нужном порядке), но это легко.

Благодарю за ответ.

Вообще несовсем все понятно.

А нет ли готовой программы в качестве примера?

Я уже третий день пытаюсь чтонибудь добиться, но безуспешно. Научился лишь выводить один знак на индикатор.

Ниже мой код может хотябы подскажеш как его сделать хотябы на 6-ть разрядов

//********************************************************

#include <mega8.h>

unsigned char led=4;

unsigned char S;

void main(void)

{

switch (led) {

case 0: (S=0b00111111); break;

case 1: (S=0b00000110); break;

case 2: (S=0b01011011); break;

case 3: (S=0b01001111); break;

case 4: (S=0b01100110); break;

case 5: (S=0b01101101); break;

case 6: (S=0b01111101); break;

case 7: (S=0b00000111); break;

case 8: (S=0b01111111); break;

case 9: (S=0b01101111); break;

}

DDRD=0xff;

PORTD=~S;

while(1);

}

//*********************************************

Заранее благодарю!!!

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

#include <mega8.h>
unsigned char ind[6]={0,0,0,0,0,0};// отображаемые знаки

// кодировка символов
// параметр - символ
unsigned char symbol_2_bin(unsigned char symbol) 
{
  unsigned char result;

  switch (symbol) { 
  case 0: (result=0b00111111); break; 
  case 1: (result=0b00000110); break;
  case 2: (result=0b01011011); break;
  case 3: (result=0b01001111); break;
  case 4: (result=0b01100110); break;
  case 5: (result=0b01101101); break;
  case 6: (result=0b01111101); break;
  case 7: (result=0b00000111); break;
  case 8: (result=0b01111111); break;
  case 9: (result=0b01101111); break;
}
return result;
}

// вывод одного символа в данном разряде
// параметры - номер разряда, выводимый знак
void indicate_one{unsigned char digit, unsigned char symbol)
{
  char i;

  switch(digit)
  {
  case 0:PORTB=0x01;break;
  case 1:PORTB=0x02;break;
  case 2:PORTB=0x04;break;
  case 3:PORTB=0x08;break;
  case 4:PORTB=0x10;break;
  case 5:PORTB=0x20;break;
  }
  PORTD=~symbol_2_bin(symbol);

  i=0;
  while(i<50)i++;// задержка символа на индикаторе
}

// вывод на индикатор всего содержимого массива ind[]
void indicate_all(void)
{
  char i;
  for(i=0;i<=5;i++)
  {
  indicate_one(i,ind[i]);
  PORTB=0x00;// гасим индикатор
  PORTD=0xff;
  }
}

void main(void)
{
  DDRD=0xff;
  DDRB=0xff;

  while(1)
  {
   ...
  }
}

у меня лично эти три функции в отдельном файле .h и везде, где надо, идут уже шаблонно, еле вспомнил, что есть что здесь :)

а разбить число на цифры можно следующим образом (применительно к 6-разрядному индикатору, число тоже должно быть шестиразрядным.)

unsigned number;
unsigned char ind[6]={0,0,0,0,0,0};
unsigned char i;
...
i=0;
for(i=0;i<=5;i++)
{
  ind[i]=number%10;
  number/=10;
}

если исходное число вещественное, то стоит домножить его на 10 в какой-нить степени, чтоб получить шестизначную целую часть.

73 de R9FDJ ex. UB8FCG | QTH LO88AA, PM-03, Пермь | RCWC #1256

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

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

//************************************************************************

#include <mega8.h>

unsigned char number,i,result,ind[6]={0,0,0,0,0,0}; // отображаемые знаки

// кодировка символов

// параметр - символ

unsigned char symbol_2_bin(unsigned char symbol)

{

switch (symbol) {

case 0: (result=0b00111111); break;

case 1: (result=0b00000110); break;

case 2: (result=0b01011011); break;

case 3: (result=0b01001111); break;

case 4: (result=0b01100110); break;

case 5: (result=0b01101101); break;

case 6: (result=0b01111101); break;

case 7: (result=0b00000111); break;

case 8: (result=0b01111111); break;

case 9: (result=0b01101111); break;

}

return result;

}

// вывод одного символа в данном разряде

// параметры - номер разряда, выводимый знак

void indicate_one(unsigned char digit, unsigned char symbol)

{

PORTD=~symbol_2_bin(symbol);

switch(digit)

{

case 0:PORTB=0x01;break;

case 1:PORTB=0x02;break;

case 2:PORTB=0x04;break;

case 3:PORTB=0x08;break;

case 4:PORTB=0x10;break;

case 5:PORTB=0x20;break;

}

i=0;

while(i<50)i++;// задержка символа на индикаторе

}

// вывод на индикатор всего содержимого массива ind[]

void indicate_all(void)

{

unsigned char i;

for(i=0;i<=5;i++)

{

//********************************************************

//Расбить число на цифры /* Как я понял код отвечающий за деление числа на цифры

ind=number%10; я должен был вставить сюда. */

number/=10;

//********************************************************

indicate_one(i,ind);

PORTB=0x00;// гасим индикатор

PORTD=0xff;

}

}

void main(void)

{

DDRD=0xff;

DDRB=0xff;

while(1)

{

number=0;

indicate_all();

}

}

//**********************************************************************************************************

За программу благодарю. С самой программой разобрался за исключением участка отвечающего за деление числа на цифры.

Проверял на железе если number = значение имеющее более одного знака на индикаторе загараются все знаки. Если что не так

прошу исправить.

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

а, забыл написать... разбивать на цифры надо где-нибудь перед индикацией всего сразу, не в функции.

например:

...
while(1)
{
...
number=123456;
// здесь разбивка на цифры
for(i=0;i<=5;i++)
{
  ind[i]=number%10;
  number/=10;
}
// здесь индикация
indicate_all();
}

73 de R9FDJ ex. UB8FCG | QTH LO88AA, PM-03, Пермь | RCWC #1256

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

//*****************************************************************************************

#include <mega8.h>

unsigned char ind[6]={0,0,0,0,0,0};// отображаемые знаки

unsigned number;

unsigned char i,n;

// кодировка символов

// параметр - символ

unsigned char symbol_2_bin(unsigned char symbol)

{

unsigned char result;

switch (symbol) {

case 0: (result=0b00111111); break;

case 1: (result=0b00000110); break;

case 2: (result=0b01011011); break;

case 3: (result=0b01001111); break;

case 4: (result=0b01100110); break;

case 5: (result=0b01101101); break;

case 6: (result=0b01111101); break;

case 7: (result=0b00000111); break;

case 8: (result=0b01111111); break;

case 9: (result=0b01101111); break;

}

return result;

}

// вывод одного символа в данном разряде

// параметры - номер разряда, выводимый знак

void indicate_one(unsigned char digit, unsigned char symbol)

{

PORTD=~symbol_2_bin(symbol);

switch(digit)

{

case 0:PORTB=0x01;break;

case 1:PORTB=0x02;break;

case 2:PORTB=0x04;break;

case 3:PORTB=0x08;break;

case 4:PORTB=0x10;break;

case 5:PORTB=0x20;break;

}

n=0;

while(n<50)n++;// задержка символа на индикаторе

}

// вывод на индикатор всего содержимого массива ind[]

void indicate_all(void)

{

for(i=0;i<=5;i++)

{

indicate_one(i,ind);

PORTB=0x00;// гасим индикатор

PORTD=0xff;

}

}

void main(void)

{

DDRD=0xff;

DDRB=0xff;

while(1)

{

number=12345;

// здесь разбивка на цифры

for(i=0;i<=5;i++)

{

ind=number%10;

number/=10;

}

// здесь индикация

indicate_all();

}

}

//********************************************************************************************

да теперь программа работает как надо и пожалуй последний вопрос:

Как управлять точками например если я подключу переключатели к порту С.

Заранее благодарен!!!

Изменено пользователем Dimas19904
Ссылка на комментарий
Поделиться на другие сайты

а вот с точками я сам понять не могу толком... у меня индикаторы на порте D висят, точка подключена на PORTD7, при индикации в нужном разряде засылаю в бит значение.

здесь у меня вариант для фиксированного положения точки во 2 разряде

void indicate_one(unsigned char digit, unsigned char symbol)
{

PORTD=~symbol_2_bin(symbol);
switch(digit)
{
case 0:PORTB=0x01;break;
case 1:PORTB=0x02;break;
case 2:PORTB=0x04;break;
case 3:PORTB=0x08;break;
case 4:PORTB=0x10;break;
case 5:PORTB=0x20;break;
}

if(digit==1)PORTD=(0<<(7));

n=0;
while(n<50)n++;// задержка символа на индикаторе
}

конкретно, не могу сообразить, что за переключатели на порте C :) что-то сегодня моск не туда работает :)

73 de R9FDJ ex. UB8FCG | QTH LO88AA, PM-03, Пермь | RCWC #1256

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

С точками я пока решил отложить. Как я писал выше я хочу cделать частотомер. Я переделал в динамической индикации

выбор разряда на порт С, а выбор сегментов индикаторов на порт В, так как мне нужно использовать внешнее прерывание (INT0).

Мне надо чтобы мк считал в течение 20 миллисекунд на INT0 колличестов импульсов и присваивал полученный

результат number. Что-то до меня недоходит как это сделать.

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

unsigned int i=0, number=0;

// External Interrupt 0

interrupt [EXT_INT0] void ext_int0_isr(void)

{

i++;

}

// Timer0 interrupt (можно другой таймер использовать)

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{ // Таймер настраиваешь на 20 ms

number=i;

i=0;

TCCR0=0x00;

}

Примерно так. Извини, если коротко написал просто времени нет...

Изменено пользователем IGRISE
Ссылка на комментарий
Поделиться на другие сайты

Я подключил к порту кнопку. Мне надо что бы при однократном нажатии на кнопку на порте устанавливалась 1, а при следующем нажатии ноль. Что то наподобии тригера. Можно ли это сделать без использования прерывания? и если

да то как?

Заранее благодарен!!!

Изменено пользователем Dimas19904
Ссылка на комментарий
Поделиться на другие сайты

Dimas19904, чем же тебе так прерывания, то не нравятся??? Без прерывания конечно можно...

Во первых их у ATmega8 всего два, а во вторых для меня проще написать программу без использования прерывания.

Незнаю может быть я и неправ.

А как сделать это без прерывания? Может кто написать программу?

Изменено пользователем Dimas19904
Ссылка на комментарий
Поделиться на другие сайты

Ну я тебе так, на словах пока разьясню:

Ты наверно имел ввиду без прерывания от INT0 и INT1, раз ты указал что их всего два...

Да написать программу без прерывания можно, но только мало кто так делают, если у тебя МК не занят другими задачами то используй просто задержки delay_ms(); delay_us();

Ну вот например делаешь так:

Считываешь состояние порта: save_first = PINX.X;

Ждешь 20 милли секунд: delay_ms(20);

Считываешь состояние порта: save_final = PINX.X;

Сравниваешь эти два значения, для подаления "дребезга контактов": if ((!f_new_key)&(save_first==save_final)) f_new_key=1; // получили новое значение от вывода, теперь можно использовать save_first или save_final для управления программой... если хочешь получить состояние кнопки тебе нужно обнулить флаг f_new_key=1;

Ждешь 20 милли секунд: delay_ms(20);

И все это зацикливаешь...

Только ты сам понимаешь, что обычно МК не только считывает состояние кнопки, но и еще что-то делает, поэтому использование функций delay_ms(); delay_us(); несколько замедлит выполнение программы, вместо того, чтобы МК что-то выполнял, он будет тупо сидеть в этих функциях и ждать, поэтому без прерывания от какого-нибудь таймера никак не обойтись... Удачи... :)

Dimas19904 ответил: для меня проще написать программу без использования прерывания

Можешь не использовать прерывания, а просто считывать флаг состояния прерывания, но тогда тебе придется принудительно после чтения обнулять эти флаги... Сразу оговорюсь, я так никогда не делал, но это конечно не озночает, что другие так не делали, попробуй... :)

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

Да, я имел ввиду внешние прерывания INT0, INT1.

Только ты сам понимаешь, что обычно МК не только считывает состояние кнопки, но и еще что-то делает, поэтому использование функций delay_ms(); delay_us(); несколько замедлит выполнение программы, вместо того, чтобы МК что-то выполнял, он будет тупо сидеть в этих функциях и ждать, поэтому без прерывания от какого-нибудь таймера никак не обойтись... Удачи...

Спасибо, теперь я понял, что лучше использовать прерывания чем искать способ написания программы без использования прерываний.

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

В дальнейшем я постараюсь разобраться с прерываниями получше!!!

Еще у меня такой вопрос: Мне надо подключить к порту матрицу из кнопок 4х4 тоесть 16 кнопок. Мне надо программу которая опрашивала бы состояние кнопок и присваивала результат опроса како-нибудь переменной.

Заранее благодарен.

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

Ну вот я набросал примерный код, а так можно посмотреть на сайте Atmel, там много примеров даже такой есть какой ты просишь

void timer0_init()
{
// Используется для клавиатуры
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: CTC top=OCR0
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0xff;  // Происходит прерывание каждые 16,32 ms
}

interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
/* Опрос клавиатуры (Клавиатура 4x4 подключена к порту X) */
DDRX=0xf0;	
PORTX=0x0f;  
key=PINX;  
DDRX=0x0f;   
PORTX=0xf0;  
key+=PINX;
key //это переменная которая содержит, код нажатой клавиши
}

Надеюсь пебе все понятно... Потому что я до Вторника сюда не буду приходить...

IGRISE уехал на отдых... :-)

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

Есть еще такой вариант динамической индикации. Только сегодня написал. На железе пока не пробовал, пока только на протеусе.

//********************************************************************************************

#include <mega8.h> //0 1 2 3 4 5 6 7 8 9

flash unsigned char ind[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

unsigned char indt[6]={0,0,0,0,0,0};

unsigned char n,k,i,result;

unsigned long number;

void main(void) {

DDRC=0xff;

DDRB=0xff;

while(1) {

number=123456;

for(i=0;i<=5;i++)

{

indt=number%10;

number/=10;

}

for (i=0;i<=5;i++) {

n=indt;

PORTB=~ind[n];

switch(i) {

case 0: result=1; break;

case 1: result=2; break;

case 2: result=4; break;

case 3: result=8; break;

case 4: result=16; break;

case 5: result=32; break;

}

PORTC=result;

k=0;

while(k<50)k++;

PORTC=0x00;

PORTB=0xff;

} //for

} //while

} //main

//******************************************************************************************

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

Меня знакомый парень попросил написать ему программу на си для ATmega8

Вот собственно:

/**********************************************************************************************

#include <mega8.h>

#include <delay.h>

interrupt[EXT_INT0] void ext_int0_isr(void) { //сюда программа попадет при "встрече припятствия"

PORTD.0=0;

PORTD.1=0;

PORTD.4=0;

delay_ms(300); //пауза для остановки машины перед движением назад

PORTD.5=1;

PORTD.0=1;

delay_ms(3000);

PORTD.0=0;

PORTD.5=0;

delay_ms(1000);

}

void port_init() {

#asm("cli") //запретить прерывания во время паузы

DDRD= 0x73;

GICR |=0x40; // INT0 вкл, INT1 выкл

MCUCR=0x0A;

GIFR=0x40;

ACSR=0x80; //Аналоговый компаратор выключен (для уменьшения энергопотребления)

SFIOR=0x00;

} //port_init

void main(void) {

port_init(); //установка состояний портов, прерывания запрещены

delay_ms(2000); //Задержка 5сек

#asm("sei") //по окончанию паузы после включения разрешить прерывания

//*************************************************************************

//Начать движение с первой скоростью ****************************************

PORTD.0=1; // Включить двигатель

delay_ms(3000); //установка времени движения с первой скоростью

PORTD.0=0; // Выключить двигатель

//*************************************************************************

//Начать движение со второй скоростью ****************************************

PORTD.1=1; // Включить двигатель

delay_ms(3000); //установка времени движения со второй скоростью

PORTD.1=0; // Выключить двигатель

//*************************************************************************

//Начать движение с третьей скоростью ****************************************

while(1) { //Бесконечный цикл

PORTD.4=1; // Включить двигатель

delay_ms(3000); //установка времени движения с третьей скоростью

//*************************************************************************

} //while

} //main

/********************************** **************************************************************

Вот мой вопрос:

После того как все условия в прерывание INT0 будут выполнены мне надо что-бы программа началась выполняться

с вот этого участка:

/********************************************************************************

//*************************************************************************

//Начать движение с первой скоростью ****************************************

PORTD.0=1; // Включить двигатель

delay_ms(3000); //установка времени движения с первой скоростью

PORTD.0=0; // Выключить двигатель

//*************************************************************************

//Начать движение со второй скоростью ****************************************

PORTD.1=1; // Включить двигатель

delay_ms(3000); //установка времени движения со второй скоростью

PORTD.1=0; // Выключить двигатель

//*************************************************************************

//Начать движение с третьей скоростью ****************************************

while(1) { //Бесконечный цикл

PORTD.4=1; // Включить двигатель

delay_ms(3000); //установка времени движения с третьей скоростью

//*************************************************************************

} //while

} //main

/**********************************************************************************

Как мне это сделать ??? Плизззззззз, кто-нибудь подскажите, очень надо!!!!

Заранее благодарен!!!!!!!!!!!!!!!!!!!!!!

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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

  Разрешено использовать не более 75 эмодзи.

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...