Нескольно простых вопросов о программировании AVR на Си.
- baron_P
- Нашел транзистор. Понюхал.
- Сообщения: 183
- Зарегистрирован: Вт сен 14, 2010 23:07:10
- Откуда: Ростов
Re: Нескольно простых вопросов о программировании AVR на Си.
Передатчик и приемник - два разных микроконтроллера, никак не синхронизированные. Включаем питание, по программе включется UART и там и там. Но момент то включения разный. Понятно, что определенный, но не для контроллеров относительно друг друга.
We do what we must because we can (c) GLaDOS
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
Если передатчик постоянно, без всяких пауз, долбит байт за байтом - руки оторвать такому разработчику.
Между пакетами в передатчике всегда делается пауза, для синхронизации с ним приёмной стороны.
Если пауз никаких нет, то вы никак не ссинхронизируетесь ни со старт-битом, ни, тем более, с началом пакета.
Между пакетами в передатчике всегда делается пауза, для синхронизации с ним приёмной стороны.
Если пауз никаких нет, то вы никак не ссинхронизируетесь ни со старт-битом, ни, тем более, с началом пакета.
Re: Нескольно простых вопросов о программировании AVR на Си.
baron_P писал(а):начнется передача на передатчике и прием на приемнике (жуть какая)
Ну это алгоритм работы Одесского базара. В реальных сетях есть, как правило, мастер и слейв. Работают они по логическому протоколу. Мастер дает запрос, слейв (-ы ) отвечает.
Если надо врубиться в чужую сеть ( шпионские страсти ), то надо дождаться тайм-аута ( состояние стоп-біта в течение времени > времені передачі одного байта [ блін, на украінскую раскладку перескочіло - хакеры ? - у меня на компе ее нет!] ) . І с этого момента ждать стартового біта. Прі этом нужно знать параметры передачі ( см. выше ) . Теоретіческі можно, думаю, программно іх определіть і к нім подстроіться, практіческі мне не пріходілось, да і нах.
Но это уже далеко за рамкамі спрошенного вопроса.
- baron_P
- Нашел транзистор. Понюхал.
- Сообщения: 183
- Зарегистрирован: Вт сен 14, 2010 23:07:10
- Откуда: Ростов
Re: Нескольно простых вопросов о программировании AVR на Си.
Аlex писал(а):Если передатчик постоянно, без всяких пауз, долбит байт за байтом - руки оторвать такому разработчику.
Между пакетами в передатчике всегда делается пауза, для синхронизации с ним приёмной стороны.
Если пауз никаких нет, то вы никак не ссинхронизируетесь ни со старт-битом, ни, тем более, с началом пакета.
Спасибо, в том и был вопрос. Синхронизация идет через паузу передатчика. В обучалках этот момент мне не попадался в явном виде, а сам долго доходил до самой необходимости такой синхронизации при асинхронной передаче. Теперь стало ясно, чего оно у меня не шевелится.
We do what we must because we can (c) GLaDOS
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
Ой, что-то Вы темните - разве "ы" есть в украинской раскладке? Да и "и" в ней вроде как на том же месте, что и в русской.Jack_A писал(а): блін, на украінскую раскладку перескочіло - хакеры ? - у меня на компе ее нет!
Re: Нескольно простых вопросов о программировании AVR на Си.
Пис'ал с обчественного компа и вдруг ни с того ни с сего EN=B RU=i . Раскладка, конечно, нашенская, белорусская. Но откуда ей взяться ? Впрочем, комп ничейный, лапают кому не лень. Могло быть и хуже.
Re: Нескольно простых вопросов о программировании AVR на Си.
объясните мне тупому пожалуйста, как работать с глобальными переменными. Почему компилится с ошибками?
- Вложения
-
- test_c.rar
- проектик на 5 строчек
- (3.78 КБ) 201 скачивание
- rxstart1
- Вымогатель припоя
- Сообщения: 508
- Зарегистрирован: Пт фев 22, 2013 18:00:43
- Откуда: Беларусь, г. Гомель
Re: Нескольно простых вопросов о программировании AVR на Си.
Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"
надо прописать #include "sub1.c"
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
господи, ну сколько можно?!rxstart1 писал(а):Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"
никогда не подключайте сишные файлы директивой #include !!!!
ну хотя бы самый простенький букварик по Си прочтите, наконец!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
ARV писал(а):господи, ну сколько можно?!rxstart1 писал(а):Во первых не подключена ни одна библиотека, а во вторых не подключена библиотека sub1.c
надо прописать #include "sub1.c"![]()
![]()
![]()
никогда не подключайте сишные файлы директивой #include !!!!
ну хотя бы самый простенький букварик по Си прочтите, наконец!
Ну это понятно, а по существу?
Ну все разобрался, всем спасибо...
Re: Нескольно простых вопросов о программировании AVR на Си.
Всем, Привет! Никто не работал с OLED дисплеем на контроллере SSD1306? как закрасить любой пиксель на экране?
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
Информации просто море по нему, в чём конкретно проблема ?
Re: Нескольно простых вопросов о программировании AVR на Си.
Да хочу функцию написать по закрашиванию пикселя по координатам
что то вроде:
x = 50;
y = 60;
draw_pixel(x, y);
собственно мне нужны команды для выхода на эти координаты, пока есть только идея использовать 21h и 22h, но там сообщение длинное получается
Еще я по команде 81h не могу изменить контраст(((
У меня пока получился такой вариант:
что то вроде:
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
}
Re: Нескольно простых вопросов о программировании AVR на Си.
Добрый день, подскажите как более правильно организовать следующую библиотеку.
service_timer.с
service_timer.h
Используется она достаточно просто servic_timer запускаем в таймер и всё дальше только работаем с Enum и не забываем изменять MAX_TIMERS
Так вот проблема в том что в одном проекте может быть 5 счётчиков в другом 10 в третьем 25
по этому файл service_timer.h от проекта к проекту меняется и приходится копировать его, что я думаю не совсем правильно.
А создавать ещё один файл который содержит только enum тоже как-то не то.
Как в таком случае создать библиотеку? (единую для всех проектов)
и где и как лучше разместить различия?
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 на Си.
вообще-то в Си "библиотекой" принято называть специальным образом скомпилированный объектный файл. а когда вы работаете с исходниками, это и называется "исходник", библиотекой это называем мы некорректно.
так вот, настоящая библиотека, например, math, собирается единожды и затем уже никак не позволяет вам менять макросы, которые были при ее сборке определены, хотя в math.h у вас эти макросы перечислены и вроде бы даже доступны для изменения. эти изменения никак не повлияют на библиотеку, только на ваши исходники.
поэтому если вы все-таки будете работать с исходниками, в вашем подходе нет никакого криминала, более того, копирование исходников - это чуть ли не единственно корректный подход в этом случае!
но если уж вы совсем щепитильно хотите следить за неизменностью "основного" кода вашей "библиотеки", можете сделать что-то вроде этого:то есть если "где-то раньше" не определен макрос MAX_TIMERS, будет использовано дефолтное значение, а если определено - то оно и будет использовано. таким образом в своем проекте вы получаете право делать любое количество таймеров, не влезая в "основной код либы".
так вот, настоящая библиотека, например, math, собирается единожды и затем уже никак не позволяет вам менять макросы, которые были при ее сборке определены, хотя в math.h у вас эти макросы перечислены и вроде бы даже доступны для изменения. эти изменения никак не повлияют на библиотеку, только на ваши исходники.
поэтому если вы все-таки будете работать с исходниками, в вашем подходе нет никакого криминала, более того, копирование исходников - это чуть ли не единственно корректный подход в этом случае!
но если уж вы совсем щепитильно хотите следить за неизменностью "основного" кода вашей "библиотеки", можете сделать что-то вроде этого:
Код: Выделить всё
#ifndef MAX_TIMERS
#define MAX_TIMERS DEFAULT_MAX_TIMERS
#endifесли рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
не могу понять откуда берется этот указатель *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 на Си.
не могу понять, что вы не можете понять?mastech писал(а):не могу понять откуда берется этот указатель *string и *data (если это конечно указатель на массив )?
mastech писал(а):void lcd_string(unsigned char command, char *string)
{
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
string (в функции lcd_string) - это указатель на char, data (в функции I2CReadByte) - указатель на uint8_t. Оно же прямо там и написано.
Re: Нескольно простых вопросов о программировании AVR на Си.
зачем объявлять указатель и не указывать не на одну переменную? и почему не дать просто имя?
в моем понимании чтоб *string использовать надо где то указать на какую переменную он должен указывать.
unsigned char i;
unsigned char *string;
string=&i;
или в функциях другие правила указателя?
в моем понимании чтоб *string использовать надо где то указать на какую переменную он должен указывать.
unsigned char i;
unsigned char *string;
string=&i;
или в функциях другие правила указателя?
Последний раз редактировалось mastech Ср июл 15, 2015 14:11:25, всего редактировалось 1 раз.