Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение baron_P »

Передатчик и приемник - два разных микроконтроллера, никак не синхронизированные. Включаем питание, по программе включется UART и там и там. Но момент то включения разный. Понятно, что определенный, но не для контроллеров относительно друг друга.
We do what we must because we can (c) GLaDOS
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Аlex »

Если передатчик постоянно, без всяких пауз, долбит байт за байтом - руки оторвать такому разработчику.
Между пакетами в передатчике всегда делается пауза, для синхронизации с ним приёмной стороны.
Если пауз никаких нет, то вы никак не ссинхронизируетесь ни со старт-битом, ни, тем более, с началом пакета.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Jack_A »

baron_P писал(а):начнется передача на передатчике и прием на приемнике (жуть какая)

Ну это алгоритм работы Одесского базара. В реальных сетях есть, как правило, мастер и слейв. Работают они по логическому протоколу. Мастер дает запрос, слейв (-ы ) отвечает.
Если надо врубиться в чужую сеть ( шпионские страсти ), то надо дождаться тайм-аута ( состояние стоп-біта в течение времени > времені передачі одного байта [ блін, на украінскую раскладку перескочіло - хакеры ? - у меня на компе ее нет!] ) . І с этого момента ждать стартового біта. Прі этом нужно знать параметры передачі ( см. выше ) . Теоретіческі можно, думаю, программно іх определіть і к нім подстроіться, практіческі мне не пріходілось, да і нах.
Но это уже далеко за рамкамі спрошенного вопроса.
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение baron_P »

Аlex писал(а):Если передатчик постоянно, без всяких пауз, долбит байт за байтом - руки оторвать такому разработчику.
Между пакетами в передатчике всегда делается пауза, для синхронизации с ним приёмной стороны.
Если пауз никаких нет, то вы никак не ссинхронизируетесь ни со старт-битом, ни, тем более, с началом пакета.

Спасибо, в том и был вопрос. Синхронизация идет через паузу передатчика. В обучалках этот момент мне не попадался в явном виде, а сам долго доходил до самой необходимости такой синхронизации при асинхронной передаче. Теперь стало ясно, чего оно у меня не шевелится.
We do what we must because we can (c) GLaDOS
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

Jack_A писал(а): блін, на украінскую раскладку перескочіло - хакеры ? - у меня на компе ее нет!
Ой, что-то Вы темните - разве "ы" есть в украинской раскладке? Да и "и" в ней вроде как на том же месте, что и в русской.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Jack_A »

Пис'ал с обчественного компа и вдруг ни с того ни с сего EN=B RU=i . Раскладка, конечно, нашенская, белорусская. Но откуда ей взяться ? Впрочем, комп ничейный, лапают кому не лень. Могло быть и хуже.
emax
Первый раз сказал Мяу!
Сообщения: 38
Зарегистрирован: Пт мар 07, 2014 18:37:20
Откуда: Пермь

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение emax »

объясните мне тупому пожалуйста, как работать с глобальными переменными. Почему компилится с ошибками?
Вложения
test_c.rar
проектик на 5 строчек
(3.78 КБ) 201 скачивание
Аватара пользователя
rxstart1
Вымогатель припоя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение rxstart1 »

Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"
emax
Первый раз сказал Мяу!
Сообщения: 38
Зарегистрирован: Пт мар 07, 2014 18:37:20
Откуда: Пермь

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение emax »

rxstart1 писал(а):Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"


проверил, не помогло, может не туда прописываю?

Изображение
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

rxstart1 писал(а):Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"
господи, ну сколько можно?! :kill: :kill: :kill:
никогда не подключайте сишные файлы директивой #include !!!!
ну хотя бы самый простенький букварик по Си прочтите, наконец!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
emax
Первый раз сказал Мяу!
Сообщения: 38
Зарегистрирован: Пт мар 07, 2014 18:37:20
Откуда: Пермь

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение emax »

ARV писал(а):
rxstart1 писал(а):Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"
господи, ну сколько можно?! :kill: :kill: :kill:
никогда не подключайте сишные файлы директивой #include !!!!
ну хотя бы самый простенький букварик по Си прочтите, наконец!


Ну это понятно, а по существу?

Ну все разобрался, всем спасибо...
Joni999
Родился
Сообщения: 15
Зарегистрирован: Пн май 05, 2014 11:59:11

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Joni999 »

Всем, Привет! Никто не работал с OLED дисплеем на контроллере SSD1306? как закрасить любой пиксель на экране?
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Аlex »

Информации просто море по нему, в чём конкретно проблема ?
Joni999
Родился
Сообщения: 15
Зарегистрирован: Пн май 05, 2014 11:59:11

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Joni999 »

Да хочу функцию написать по закрашиванию пикселя по координатам
что то вроде:
x = 50;
y = 60;
draw_pixel(x, y);
собственно мне нужны команды для выхода на эти координаты, пока есть только идея использовать 21h и 22h, но там сообщение длинное получается
Еще я по команде 81h не могу изменить контраст(((

У меня пока получился такой вариант:

Код: Выделить всё

void draw_pixel_lcd(uint8_t _adress, uint8_t _x, uint8_t _y){
   uint8_t __x = 0;
   while(_x > 7){
       _x -= 8;
       __x ++;
   }   
   send_command_lcd(_adress, 0x21);   //Set Column Address (21h)
   send_command_lcd(_adress, _y);
   send_command_lcd(_adress, _y);
   send_command_lcd(_adress, 0x22);   //Set Page Address (22h)
   send_command_lcd(_adress, __x);
   send_command_lcd(_adress, __x);
   send_data_lcd(_adress, 1<<_x);       //Draw pixel
}
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение pokk »

Добрый день, подскажите как более правильно организовать следующую библиотеку.

service_timer.с
Спойлер

Код: Выделить всё

#include <service_timer.h>

volatile unsigned int Timir[MAX_TIMERS];


unsigned int GetTimers(unsigned char timers){
      return Timir[timers];
}
void ResetTimers(unsigned char timers){
      Timir[timers]=0;
}
void StartTimers(unsigned char timers){
      Timir[timers]=0xFFFD; //65533 2ms что бы дошло до нужного места программы
}

void servic_timer(void){
    unsigned char i=0;
   for (i=0; i<MAX_TIMERS; i++) {
      Timir[i]++;
      //-----Доработка что бы таймеры не обнулился после переполнения-----
      if(Timir[i]>0xFFFA){ //65530 (5 едениц запас)
         Timir[i]=0xFFFA;
      }
   }
}


service_timer.h
Спойлер

Код: Выделить всё

#ifndef service_timer_h_
#define service_timer_h_
//******************************************************************************
//  Секция include: здесь подключаются заголовочные файлы используемых модулей
//******************************************************************************
#include "Aplication.h"
//******************************************************************************
//  Секция определения макросов
//******************************************************************************
enum{
      TEST1,
      TEST2,
};

#define MAX_TIMERS 3
//******************************************************************************
//  Секция определения глобальных переменных
//******************************************************************************
extern volatile unsigned int Timir[MAX_TIMERS];
//******************************************************************************
//*******************Секция прототипов функций
//******************************************************************************
unsigned int GetTimers(unsigned char timers);
void ResetTimers(unsigned char timers);
void StartTimers(unsigned char timers);
void servic_timer(void);
#endif /* service_timer_h_*/
//******************************************************************************
//  ENF OF FILE
//******************************************************************************


Используется она достаточно просто servic_timer запускаем в таймер и всё дальше только работаем с Enum и не забываем изменять MAX_TIMERS

Так вот проблема в том что в одном проекте может быть 5 счётчиков в другом 10 в третьем 25
по этому файл service_timer.h от проекта к проекту меняется и приходится копировать его, что я думаю не совсем правильно.
А создавать ещё один файл который содержит только enum тоже как-то не то.
Как в таком случае создать библиотеку? (единую для всех проектов)
и где и как лучше разместить различия?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

вообще-то в Си "библиотекой" принято называть специальным образом скомпилированный объектный файл. а когда вы работаете с исходниками, это и называется "исходник", библиотекой это называем мы некорректно.

так вот, настоящая библиотека, например, math, собирается единожды и затем уже никак не позволяет вам менять макросы, которые были при ее сборке определены, хотя в math.h у вас эти макросы перечислены и вроде бы даже доступны для изменения. эти изменения никак не повлияют на библиотеку, только на ваши исходники.

поэтому если вы все-таки будете работать с исходниками, в вашем подходе нет никакого криминала, более того, копирование исходников - это чуть ли не единственно корректный подход в этом случае!

но если уж вы совсем щепитильно хотите следить за неизменностью "основного" кода вашей "библиотеки", можете сделать что-то вроде этого:

Код: Выделить всё

#ifndef MAX_TIMERS
#define MAX_TIMERS DEFAULT_MAX_TIMERS
#endif
то есть если "где-то раньше" не определен макрос MAX_TIMERS, будет использовано дефолтное значение, а если определено - то оно и будет использовано. таким образом в своем проекте вы получаете право делать любое количество таймеров, не влезая в "основной код либы".
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение mastech »

не могу понять откуда берется этот указатель *string и *data (если это конечно указатель на массив )?

Код: Выделить всё

// Функция вывода строки на LCD
void lcd_string(unsigned char command, char *string)
{
lcd_com(0x0C);
lcd_com(command);
while(*string != '\0')
{  lcd_data(*string);
string++;
}
}

Спойлер

Код: Выделить всё

// Функция чтения данных по шине
uint8_t I2CReadByte(uint8_t *data,uint8_t ack)
{
if(ack) // Устанавливаем подтверждение
{
// Возвращаем подтверждение после приема
TWCR |= (1 << TWEA);
}
else
{
// Возвращаем неподтверждение после приема
// Ведомое устройство не получает больше данных
// обычно используется для распознования последнего байта
TWCR &= ~(1 << TWEA);
}
// Разрешение приема данных после сброса TWINT
TWCR |= (1 << TWINT);
while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT
// Проверка статуса
if((TWSR & 0xF8) == 0x58 || (TWSR & 0xF8) == 0x50)
{
// Прием данных и возвращение подтверждения
//  или
// Прием данных и возвращение неподтверждения
*data = TWDR; // Читаем данные
return 1;
}
else
return 0; // Ошибка
}


Спойлер

Код: Выделить всё

 #include <avr/io.h>
#include <util/delay.h>
 
// Функция инициализация шины TWI
void I2CInit(void)
{
// настройка TWI модуля
TWBR = 2;
TWSR = (1 << TWPS1)|(1 << TWPS0); // Предделитель на 64
TWCR |= (1 << TWEN); // Включение модуля TWI
}
 
void I2CStart(void)
{
// Передача условия СТАРТ
TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTA);
// Ожидание установки флага TWINT
while(!(TWCR & (1 << TWINT)));
}
 
void I2CStop(void)
{
TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTO); // Передача условия СТОП
while(TWCR & (1 << TWSTO)); // Ожидание завершения передачи условия СТОП
}
 
// Функция записи данных по шине
uint8_t I2CWriteByte(uint8_t data)
{
TWDR = data; // Загрузка данных в TWDR 
TWCR = (1 << TWEN)|(1 << TWINT); // Сброс флага TWINT для начала передачи данных
while(!(TWCR & (1 << TWINT))); // Ожидание завершения передачи
// Проверка статуса
if((TWSR & 0xF8) == 0x18 || (TWSR & 0xF8) == 0x28 || (TWSR & 0xF8) == 0x40)
{
// Если адрес DS1307, биты R/W и данные переданы
// и получено подтверждение
return 1;
}
else
return 0; // ОШИБКА
}
 
// Функция чтения данных по шине
uint8_t I2CReadByte(uint8_t *data,uint8_t ack)
{
if(ack) // Устанавливаем подтверждение
{
// Возвращаем подтверждение после приема
TWCR |= (1 << TWEA);
}
else
{
// Возвращаем неподтверждение после приема
// Ведомое устройство не получает больше данных
// обычно используется для распознования последнего байта
TWCR &= ~(1 << TWEA);
}
// Разрешение приема данных после сброса TWINT
TWCR |= (1 << TWINT);
while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT
// Проверка статуса
if((TWSR & 0xF8) == 0x58 || (TWSR & 0xF8) == 0x50)
{
// Прием данных и возвращение подтверждения
//  или
// Прием данных и возвращение неподтверждения
*data = TWDR; // Читаем данные
return 1;
}
else
return 0; // Ошибка
}
// Функция чтения данных из DS1307
uint8_t DS1307Read(uint8_t address,uint8_t *data)
{
uint8_t res; // Результат
I2CStart(); // СТАРТ
res = I2CWriteByte(0b11010000); // адрес DS1307 + бит W
if(!res)    return 0; // ОШИБКА
// Передача адреса необходимого регистра
res = I2CWriteByte(address);
if(!res)    return 0; // ОШИБКА
I2CStart(); // Повторный СТАРТ 
res = I2CWriteByte(0b11010001); // адрес DS1307 + бит R
if(!res)    return 0; // ОШИБКА
// Чтение данных с неподтверждением
res = I2CReadByte(data,0);
if(!res)    return 0; // ОШИБКА
I2CStop(); // СТОП
return 1;
}
// Функция записи данных в DS1307
uint8_t DS1307Write(uint8_t address,uint8_t data)
{
uint8_t res; // Результат
I2CStart(); // СТАРТ
res = I2CWriteByte(0b11010000); // адрес DS1307 + бит W
if(!res)    return 0; // ОШИБКА
// Передача адреса необходимого регистра
res = I2CWriteByte(address);
if(!res)    return 0; // ОШИБКА
res = I2CWriteByte(data); // Запись данных
if(!res)    return 0; // ОШИБКА
I2CStop(); // СТОП
return 1;
}
// Функции работы с LCD
#define RS PD0
#define EN PD2
// Функция передачи команды
void lcd_com(unsigned char p)
{
PORTD &= ~(1 << RS); // RS = 0 (запись команд)
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}
// Функция передачи данных
void lcd_data(unsigned char p)
{
PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}
// Функция вывода строки на LCD
void lcd_string(unsigned char command, char *string)
{
lcd_com(0x0C);
lcd_com(command);
while(*string != '\0')
{  lcd_data(*string);
string++;
}
}
// Функция вывода переменной
void lcd_num_to_str(unsigned int value, unsigned char nDigit)
{
 switch(nDigit)
 {
  case 4: lcd_data((value/1000)+'0');
  case 3: lcd_data(((value/100)%10)+'0');
  case 2: lcd_data(((value/10)%10)+'0');
  case 1: lcd_data((value%10)+'0');
 }
}
// Функция инициализации LCD
void lcd_init(void)
{
PORTD = 0x00;
DDRD = 0xFF;
 
_delay_ms(50); // Ожидание готовности ЖК-модуля
 
// Конфигурирование четырехразрядного режима
PORTD |= (1 << PD5);
PORTD &= ~(1 << PD4);
 
// Активизация четырехразрядного режима
PORTD |= (1 << EN);
PORTD &= ~(1 << EN);
_delay_ms(5);
 
lcd_com(0x28); // шина 4 бит, LCD - 2 строки
lcd_com(0x08); // полное выключение дисплея
lcd_com(0x01); // очистка дисплея
_delay_us(100);
lcd_com(0x06); // сдвиг курсора вправо
lcd_com(0x0C); // включение дисплея, курсор не видим
}
 
int main(void)

_delay_ms(100);
 
DDRC = 0x00;
PORTC = 0xFF;
 
lcd_init(); // Инициализация LCD
I2CInit(); // Инициализация шины I2C
 
// Запускаем ход часов
uint8_t temp;
DS1307Read(0x00,&temp);
temp &= ~(1 << 7); // обнуляем 7 бит
DS1307Write(0x00,temp);
 
while(1)
{
unsigned char hour, minute, second, temp;
// Читаем данные и преобразуем из BCD в двоичную систему
DS1307Read(0x00,&temp); // Чтение регистра секунд
second = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
DS1307Read(0x01,&temp); // Чтение регистра минут
minute = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
DS1307Read(0x02,&temp); // Чтение регистра часов
hour = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
 
lcd_string(0x81, "«acГ Ѕa DS1307");
lcd_string(0xC4, "  :  :  ");
lcd_com(0xC4);
lcd_num_to_str(hour, 2); // Выводим на экран часы
lcd_com(0xC7);
lcd_num_to_str(minute, 2); // Выводим на экран минуты
lcd_com(0xCA);
lcd_num_to_str(second, 2); // Выводим на экран секунды
 
if((PINC & (1 << PC0))==0) // Если нажата кнопка
{
while((PINC & (1 << PC0))==0){} // Ждем отпускания кнопки
hour++; // Увеличиваем часы на 1
if(hour > 23) hour = 0;
// Преобразуем из двоичной системы в BCD и записываем в DS1307
uint8_t temp;
temp = ((hour/10) << 4)|(hour%10);
DS1307Write(0x02, temp);
_delay_ms(100);
}
 
if((PINC & (1 << PC1))==0) // Если нажата кнопка
{
while((PINC & (1 << PC1))==0){} // Ждем отпускания кнопки
minute++; // Увеличиваем минуты на 1
if(minute > 59) minute = 0;
// Преобразуем из двоичной системы в BCD и записываем в DS1307
uint8_t temp;
temp = ((minute/10) << 4)|(minute%10);
DS1307Write(0x01, temp);
_delay_ms(100);
}
}
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

mastech писал(а):не могу понять откуда берется этот указатель *string и *data (если это конечно указатель на массив )?
не могу понять, что вы не можете понять?
mastech писал(а):void lcd_string(unsigned char command, char *string)
{
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

string (в функции lcd_string) - это указатель на char, data (в функции I2CReadByte) - указатель на uint8_t. Оно же прямо там и написано.
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение mastech »

зачем объявлять указатель и не указывать не на одну переменную? и почему не дать просто имя?

в моем понимании чтоб *string использовать надо где то указать на какую переменную он должен указывать.

unsigned char i;
unsigned char *string;

string=&i;

или в функциях другие правила указателя?
Последний раз редактировалось mastech Ср июл 15, 2015 14:11:25, всего редактировалось 1 раз.
Ответить

Вернуться в «AVR»