Мелкие вопросы по МК и ПЛИС.

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

считывается регистр состояния ЖКИ и проверяется наличие в нем 7-го бита, который есть флаг занятости. пока он есть - крутится цикл опроса этого флага.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

Уже второй день борюсь с ошибкой компилятора, несколько раз переписывал код для дисплея, думал в этом ошибка. Но ошибка каждый раз одна и та же - multiple definition в файле lcd_main.h
интернет говорит что что-то не так с подключаемыми файлами.
Мне кажется решение где-то на поверхности, но я уже все варианты перепробовал, которые знал.

есть три файла, которые менял - lcd_lib.c, lcd_lib.h и main.c, приведу только начало, а то много кода. Файл lcd_lib.h весь, на него ругается.
Помогите советом, как это исправить.

Лог
Спойлер

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

Compiling C: lcd_lib.c
avr-gcc -c -mmcu=atmega168p -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./lcd_lib.lst  -std=gnu99 -Wundef -MMD -MP -MF .dep/lcd_lib.o.d lcd_lib.c -o lcd_lib.o 

Linking: main.elf
avr-gcc -mmcu=atmega168p -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -Wundef -MMD -MP -MF .dep/main.elf.d main.o lcd_lib.o --output main.elf -Wl,-Map=main.map,--cref     -lm
lcd_lib.o: In function `I2C_StartCondition':
E:\1\mod_168/lcd_lib.h:25: multiple definition of `I2C_StartCondition'
main.o:E:\1\mod_168/lcd_lib.h:25: first defined here
lcd_lib.o: In function `I2C_StopCondition':
E:\1\mod_168/lcd_lib.h:32: multiple definition of `I2C_StopCondition'
main.o:E:\1\mod_168/lcd_lib.h:32: first defined here
lcd_lib.o: In function `I2C_SendByte':
E:\1\mod_168/lcd_lib.h:38: multiple definition of `I2C_SendByte'
main.o:E:\1\mod_168/lcd_lib.h:38: first defined here
lcd_lib.o: In function `I2C_Init':
E:\1\mod_168/lcd_lib.h:46: multiple definition of `I2C_Init'
main.o:E:\1\mod_168/lcd_lib.h:46: first defined here
lcd_lib.o: In function `I2C_SendPocket':
E:\1\mod_168/lcd_lib.h:51: multiple definition of `I2C_SendPocket'
main.o:E:\1\mod_168/lcd_lib.h:51: first defined here
lcd_lib.o: In function `I2C_RecieveByte':
E:\1\mod_168/lcd_lib.h:63: multiple definition of `I2C_RecieveByte'
main.o:E:\1\mod_168/lcd_lib.h:63: first defined here
lcd_lib.o: In function `I2C_RecieveLastByte':
E:\1\mod_168/lcd_lib.h:73: multiple definition of `I2C_RecieveLastByte'
main.o:E:\1\mod_168/lcd_lib.h:73: first defined here
make.exe: *** [main.elf] Error 1

> Process Exit Code: 2
> Time Taken: 00:01
lcd_lib.h
Спойлер

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

#ifndef LCD_LIB_H
#define LCD_LIB_H

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

// отправка команды СТАРТ
void I2C_StartCondition(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
}

// отправка СТОП
void I2C_StopCondition(void)
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}

//отправка байта
void I2C_SendByte(unsigned char c)
{
TWDR = c;//загрузка значения в регистр данных
TWCR = (1<<TWINT)|(1<<TWEN);//начаало передачи байта данных
while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
}

//инициализация I2C как передатчика
void I2C_Init (void)
{
TWBR=0xFF;//скорость передачи
}

//отправка SLA_W + байт данных
void I2C_SendPocket (unsigned char value,unsigned char adres_rw)
{
I2C_StartCondition(); // генерируем условие СТАРТ
I2C_SendByte(adres_rw); //оправляем адрес устройства+бит запись
I2C_SendByte(value);//отправляем байт данных
I2C_StopCondition();//генерируем условие СТОП
}

//добавляем функции чтения по I2C
//чтение байта
unsigned char I2C_RecieveByte(void)
{
unsigned char dat;//переменная хранения значения
TWCR |= (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
dat = TWDR;//читаем регистр данных
return dat;
}

//чтение последнего байта
unsigned char I2C_RecieveLastByte(void)
{
unsigned char dat;//переменная хранения значения	
TWCR |= (1<<TWINT)|(1<<TWEN)|(0<<TWEA);//чтение последнего байта
while (!(TWCR & (1<<TWINT)));//ожидание установки бита TWIN
dat = TWDR;//читаем регистр данных	
return dat;
}
lcd_lib.c
Спойлер

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

#include "lcd_lib.h"
#include "codetable.h"

//адрес LCD переходника
#define LCD_ADDR 0b00100111
//макрос адреса + бит записи
#define SLA_W   LCD_ADDR<<1

//создаем переменную Эквивалент регистра порта
unsigned char Led_port=0;

//макрос отправки пакетов LCD
#define I2C_SendPocketLCD(x) I2C_SendPocket (x,SLA_W)

/*
таблица соответствия
Po - RS
P1 - R/W
P2 - E
P3 - подсветка
P4 - D4
P5 - D5
P6 - D6
P7 - D7
 */

/* установка лог. "1" на линии RS */
#define LCD_RS_SET  I2C_SendPocketLCD (Led_port|=0x01)
/* установка лог. "0" на линии RS */
#define LCD_RS_CLR  I2C_SendPocketLCD (Led_port&=~0x01)
/* установка лог. "1"(запись) R/W*/
#define LCD_RW_SET  I2C_SendPocketLCD (Led_port|=0x02)
/* установка лог. "0"(Чтение) R/W */
#define LCD_RW_CLR  I2C_SendPocketLCD (Led_port&=~0x02)
/* установка лог. "1" на линии E */
#define LCD_E_SET   I2C_SendPocketLCD (Led_port |=0x04)
/* установка лог. "0" на линии E */
#define LCD_E_CLR   I2C_SendPocketLCD (Led_port &=~0x04)
/* установка лог. "1" на линии подсветки */
#define LCD_BT_SET  I2C_SendPocketLCD (Led_port|=0x08)
/* установка лог. "0" на линии подсветки */
#define LCD_BT_CLR  I2C_SendPocketLCD (Led_port&=~0x08)

/* функция передачи тетрады в жки */
inline static void LCD_CommonFunc(unsigned char t)
{
t<<=4;
    LCD_E_SET;
    _delay_us(50);
    I2C_SendPocketLCD (Led_port|t);
    LCD_E_CLR;
    _delay_us(50);
}
main.c
Спойлер

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "lcd_lib.h"

#include "main.h"
#include <avr/wdt.h>
ISR (__vector_default) 	
{
return;					
}

//unsigned char cc=5;
ISR (TIMER0_OVF_vect)	
{
		
	static char delenie_in_two = 0;
	if(++delenie_in_two == 2)
	{
		delenie_in_two = 0;
Реклама
Друг Кота
Аватара пользователя
Сообщения: 8007
Зарегистрирован: Вс ноя 14, 2010 19:24:26
Откуда: Лукалэнд

Сообщение hybroid »

Все с ног на голову. В заголовке объявить прототипы функций, а тело в .c файле. Инлайн-функцию вынести наоборот в заголовок.
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

scorpi_0n писал(а): Следуя вашей логике уже в самом смысле отсутствует смысл.
Следуя моей логике, можно применять ровно те микросхемы, которые имеются в наличии (либо доступны) и позволяют достичь поставленной цели. Обозначение производителя не имеет вообще никакого значения.
Что до ларька с комплектацией, то покупка на али делает обозначение производителя смешным фейком. Но али, тем не менее, остается самым популярным ларьком.
Именно потому, что "даром за амбаром" стало самоцелью. И хобби на этом фоне идет лесом (см. комментарий об АД, ТИ и прочих).
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

hybroid , спасибо большое, все получилось буквально за минуту, аж не верится. До этого два дня не получалось.
Что я сделал: все #define перенес в файл lcd_lib.h, а функции наоборот в файл lcd_lib.c. После этого сразу откомпилировалось и заработало.
С прошивкой имел дело первый раз, решил в готовом проекте перейти с параллельного интерфейса на аппаратный I2C с помощью переходника PCF8574 на дисплей 1602.
И хоть я в основном копипастил, для себя это считаю прогрессом :)
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

не перестаю удивляться. Почему после таког выражения v_batt = (150*280) / 128;
в переменной v_batt находится число 65353?

Удалось победить только так:
unsigned int aa;
aa = 150*280;
v_batt = aa / 128;

Это нормально, так и должно быть? Просто в других примерах видел там одновременно умножаются и делятся большие числа и все работает.
Последний раз редактировалось hosturik Чт ноя 10, 2016 21:40:17, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3059
Зарегистрирован: Пн май 11, 2009 14:15:00
Откуда: СПб

Сообщение *Trigger* »

150*280 в 16 бит со знаком не влезает. Наверное, в этом проблема.
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
Друг Кота
Сообщения: 3342
Зарегистрирован: Ср янв 02, 2013 08:37:35

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

*Trigger* писал(а):150*280 в 16 бит со знаком не влезает.
Как число 42000 не может входить в 16 битную переменную… с каким знаком?
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

Тип unsigned так что число 42000 поместиться в два байта
Последний раз редактировалось hosturik Чт ноя 10, 2016 22:04:56, всего редактировалось 1 раз.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

hosturik писал(а):не перестаю удивляться. Почему после таког выражения v_batt = (150*280) / 128;
в переменной v_batt находится число 65353?
У меня 65353 получается. Все правильно.
150*280=42000
так как знаковое 16-тибитное число может быть только в пределах от +32767 до -32768, то данное число должно интерпертироваться, как отрицательное 65536-42000=23536
-23536/128=-183
Теперь знаком присваивания мы -183 преобразуем в беззнаковое 16-тибитное число. 65536-183=65353

Вывод, пишите U после хотя бы одного из чисел. Например так: (150U*280) / 128
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

Спасибо. А что будет если напишу U возле числа, это означает unsigned?

И то, что у меня v_batt объявлена так: volatile unsigned int v_batt; ничего не дает?
Последний раз редактировалось hosturik Чт ноя 10, 2016 22:13:33, всего редактировалось 1 раз.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Да. U - unsigned. L - long. Можно их комбинировать вместе

Добавлено after 3 minutes 40 seconds:
hosturik писал(а):
И то, что у меня v_batt объявлена так: volatile unsigned int v_batt; ничего не дает?
Если бы она участвовало в правой части оператора присваивания, то давало бы, так как когда производится операция между знаковым и беззнаковым целым, до операции знаковое будет преобразовано в беззнаковое.
Но так как оно в правой части оператора присваивания не фигурирует, то и на вычисление выражения в правой части никак не влияет.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

ADMUX = (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
часто встречаю такую конструкцию. Но разве так нули записываются?

Нули же вроде так нужно - ADMUX &=~(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0);
Чего я не понимаю?
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

hosturik писал(а):ADMUX = (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
Данная запись эквивалентна ADMUX = (1<<REFS0)|(1<<ADLAR);
Указание остальных нулевых битов компилятором будет игнорировано и никакого влияния на результирующий код не оказывает. Приведенная Вами запись используется исключительно для более удобного copy-paste )

Иными словами, сколько ноль не сдвигай, он все равно нулем останется.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Прорезались зубы
Сообщения: 249
Зарегистрирован: Вс авг 15, 2010 20:42:44
Откуда: Тюмень

Сообщение Serhio »

Всем доброго времени суток. Решил написать тут.
Задумался я над изготовлением устройства представленного здесь:
http://phreakerclub.com/forum/showthread.php?t=29
но не на пик, как там, а на авр, а именно мега8 (понимаю, что жирно, но скопилось у меня их аж 4 штуки). Занимаюсь переписыванием кода под мегу. Очередной затык возник в следующем:
Устройство просто перебирает все комбинации от двенадцати нулей до двенадцати единиц (с выплевыванием в эфир). Поскольку РОН у меги 8-ми битные, а комбинации состоят из 12 бит, то необходимо регистр (из которого методом логического сдвига данные по очереди выдаются в эфир) представить как один 12-ти битный регистр. Знаю, что в меге есть регистровые пары и можно использовать их, НО из спортивного интереса хочется понять какие есть альтернативные методы? У автора не применяются регистровые пары - он использовал пик 18f252, а там я вообще не обнаружил сдвоенные регистры, но каким-то образом данные у него поступают как из одного 16-ти битного регистра. (4 пустых сдвига + 12 бит данных). Прошу помощи опытных котов.
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

У любого процессора есть флаг переноса, в который попадает старший бит при логическом сдвиге влево или младший бит при логическом сдвиге вправо. И есть команды циклического сдвига, когда в при сдвиге влево в младший бит попадает бит переноса, а при сдвиге вправо в старший бит попадает бит переноса. Используя это можно хоть все регистры объединить в единое целое и сдвигать их совместно.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Прорезались зубы
Сообщения: 249
Зарегистрирован: Вс авг 15, 2010 20:42:44
Откуда: Тюмень

Сообщение Serhio »

спасибо. Полагаю так?
00000000 <----- 10000000
1. Сдвигаем сначала левое значение (где все нули) в бит переноса попадает ноль.
2. Затем этот флаг чистим (для надежности).
3. сдвигаем на один правое значение. Во флаг попала единица.
4. "копируем" эту единицу из флага в младший разряд левого числа и получаем
00000001 00000000

сдвиги при этом используем логические.
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

На примере AVR. Пусть у нас число располагается в двух регистрах. Старший байт в r20 и младший в r21

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

; 16 bit right shift 
  lsr r20
  ror r21
;
; 16 bit left shift 
  lsl r21
  rol r20
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Прорезались зубы
Сообщения: 249
Зарегистрирован: Вс авг 15, 2010 20:42:44
Откуда: Тюмень

Сообщение Serhio »

ptr128 писал(а):На примере AVR. Пусть у нас число располагается в двух регистрах. Старший байт в r20 и младший в r21

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

; 16 bit right shift 
  lsr r20
  ror r21
;
; 16 bit left shift 
  lsl r21
  rol r20
Благодарю. Думаю в моем случае можно сделать так

16 bit left shift
rol r21
rol r20

Потому что мы производим 16 сдвигов и после 16го остановим цикл. У автора применено именно 2 циклических сдвига и благодаря Вам я понял почему так, а не иначе. Сейчас проверю.
Контактная информация:
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

У PIC, вроде, нет логических сдвигов, поэтому действие было вынужденное. У AVR такой сдвиг есть, поэтому
ptr128 писал(а):

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

; 16 bit left shift 
  lsl r21
  rol r20
Ответить

Вернуться в «Разные вопросы по МК»