Kavka писал(а):Этот кусочек у меня не вызывает описанных вами ошибок.
Если вы не понимаете на "что конкретно" ругается компилятор, тогда тем более покажите всё что у вас пишет компилятор при компиляции.
Код: Выделить всё
Build started 28.6.2013 at 07:58:04
avr-gcc -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d -c ../main.c
avr-gcc -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT Port.o -MF dep/Port.o.d -c ../Port.c
avr-gcc -mmcu=atmega8 -Wl,-Map=Comm_rx.map main.o Port.o -o Comm_rx.elf
Port.o: In function `Port_Init':
C:\WinAVR\Project\Comm_rx\default/../Port.c:81: multiple definition of `Port_Init'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:81: first defined here
Port.o: In function `SaveAddress':
C:\WinAVR\Project\Comm_rx\default/../Port.c:97: multiple definition of `SaveAddress'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:97: first defined here
Port.o:(.eeprom+0x0): multiple definition of `eeprombyte'
main.o:(.eeprom+0x0): first defined here
Port.o: In function `ReadAddress':
C:\WinAVR\Project\Comm_rx\default/../Port.c:105: multiple definition of `ReadAddress'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:105: first defined here
Port.o: In function `Port_Set_Address':
C:\WinAVR\Project\Comm_rx\default/../Port.c:113: multiple definition of `Port_Set_Address'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:113: first defined here
Port.o: In function `Port_Get_Address':
C:\WinAVR\Project\Comm_rx\default/../Port.c:153: multiple definition of `Port_Get_Address'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:153: first defined here
Port.o: In function `Do_Crc8':
C:\WinAVR\Project\Comm_rx\default/../Port.c:353: multiple definition of `Do_Crc8'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:353: first defined here
Port.o: In function `__vector_13':
C:\WinAVR\Project\Comm_rx\default/../Port.c:271: multiple definition of `__vector_13'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:271: first defined here
Port.o: In function `__vector_11':
C:\WinAVR\Project\Comm_rx\default/../Port.c:158: multiple definition of `__vector_11'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:158: first defined here
Port.o: In function `Port_Tx_Frame':
C:\WinAVR\Project\Comm_rx\default/../Port.c:366: multiple definition of `Port_Tx_Frame'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:366: first defined here
Port.o: In function `Port_Tx_Exe':
C:\WinAVR\Project\Comm_rx\default/../Port.c:375: multiple definition of `Port_Tx_Exe'
main.o:C:\WinAVR\Project\Comm_rx\default/../Port.c:375: first defined here
collect2: ld returned 1 exit status
make: *** [Comm_rx.elf] Ошибка 1
Build failed with 1 errors and 0 warnings...Спойлер
//----------------------------------------------------------------------------//модуль реализации протокола Wake для порта RS-485.
//----------------------------------------------------------------------------
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h> // прерывания
#include "main.h"
#include "Port.h"
#include "Wake.h"
#include <util/setbaud.h> // расчет UBRR
//----------------------------- Константы: -----------------------------------
#define TX_DELAY 20 //задержка ответа, мс
//----------------------------------------------------------------------------
EEMEM uint8_t eeprombyte = 0x10; // адрес ячейки в EEPROM, где хранится адрес платы
static void uart_speed (void) { // вычисление UBRR
UBRRH=UBRRH_VALUE;
UBRRL=UBRRL_VALUE;
#if USE_2X
UCSRA |=(1<<U2X);
#else
UCSRA &=~(1<<U2X);
#endif
}
//------------------------------- Переменные: --------------------------------
unsigned char Rx_Sta, //состояние процесса приема пакета
Rx_Pre, //предыдущий принятый байт
Rx_Add, //адрес, с которым сравнивается принятый
Rx_Cmd, //принятая команда
Rx_Nbt, //принятое количество байт в пакете
Rx_Dat[FRAME], //массив принятых данных
Rx_Crc, //контрольная сумма принимаемого пакета
Rx_Ptr; //указатель на массив принимаемых данных
unsigned char Command; //код команды на выполнение
unsigned char Tx_Sta, //состояние процесса передачи пакета
Tx_Pre, //предыдущий переданный байт
Tx_Add, //адрес, передававемый в пакете
Tx_Cmd, //команда, передаваемая в пакете
Tx_Nbt, //количество байт данных в пакете
Tx_Dat[FRAME], //массив данных для передачи
Tx_Crc, //контрольная сумма передаваемого пакета
Tx_Ptr; //указатель на массив передаваемых данных
static unsigned char TxTimer;//таймер задержки передачи ответа через RS-485
static unsigned char Adress; //адрес платы
//-------------------------------- Функции: ----------------------------------
ISR (USART_TXC_vect); //прерывание после передачи байта
ISR (USART_RXC_vect); //прерывание после приема байта
void Port_Init(void); //инициализация порта
void Port_Set_Address(void); //установка адреса платы
void Port_Tx_Frame(void); //запрос передачи пакета
void Port_Tx_Exe(bool t); //передача пакета с задержкой ответа
void SaveAddress(char addr);
unsigned char ReadAddress(void);
void Port_Set_Address(void);
unsigned char Port_Get_Address(void);
void Do_Crc8(unsigned char b, unsigned char *crc); //вычисление контрольной суммы
//------------------------ Инициализация UART: -------------------------------
void Port_Init(void)
{
UCSRC = (1<<UCSZ1) | (1<<UCSZ0); //8-битная посылка
uart_speed(); //задание скорости обмена
//разрешение прерываний по приему и передаче, разрешение приема и передачи
UCSRB = (1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN);
//Rx_Add = ReadAddress(); //чтение адреса из EEPROM
Tx_Add = Rx_Add; //адрес на передачу равен адресу на прием
Rx_Sta = WAIT_FEND; //ожидание пакета
Tx_Sta = SEND_IDLE; //ничего пока не передаем
Command = CMD_NOP; //нет команды на выполнение
}
//----------------------- Сохранение адреса в EEPROM: ------------------------
void SaveAddress(char addr)
{
eeprom_write_byte(&eeprombyte, addr);
}
//------------------------- Чтение адреса из EEPROM: -------------------------
unsigned char ReadAddress(void)
{
unsigned char a = eeprom_read_byte(&eeprombyte);
return(a);
}
//----------------------- Установка адреса устройства: -----------------------
void Port_Set_Address(void) // установка адреса платы по джамперам
{
Adress=0; // обнуляем переменную адреса платы
if BitIsSet(ADDR,ADDR_1) // выставляем 0-й бит адреса
{
SetBit(Adress,0);
}
else
{
ClearBit(Adress,0);
}
if BitIsSet(ADDR,ADDR_2) // выставляем 1-й бит адреса
{
SetBit(Adress,1);
}
else
{
ClearBit(Adress,1);
}
if BitIsSet(ADDR,ADDR_3) // выставляем 2-й бит адреса
{
SetBit(Adress,2);
}
else
{
ClearBit(Adress,2);
}
if BitIsSet(ADDR,ADDR_4) // выставляем 3-й бит адреса
{
SetBit(Adress,3);
}
else
{
ClearBit(Adress,3);
}
}
//------------------------ Чтение адреса устройства: -------------------------
unsigned char Port_Get_Address(void)
{
return(Rx_Add);
}
//------------------- Прерывание UART после приема байта: --------------------
ISR (USART_RXC_vect)
{
char error_flags = (UCSRA & (1<<FE)); //чтение флагов ошибок
char data_byte = UDR; //чтение данных
if(error_flags) //если обнаружены ошибки при приеме байта
{
Rx_Sta = WAIT_FEND; //ожидание нового пакета
Command = CMD_ERR; //рапортуем об ошибке
return;
}
if(data_byte == FEND) //если обнаружено начало фрейма,
{
Rx_Pre = data_byte; //то сохранение пре-байта,
Rx_Crc = CRC_INIT; //инициализация CRC,
Rx_Sta = WAIT_ADDR; //сброс указателя данных,
Do_Crc8(data_byte, &Rx_Crc); //обновление CRC,
return; //выход
}
if(Rx_Sta == WAIT_FEND) //-----> если ожидание FEND,
return; //то выход
char Pre = Rx_Pre; //сохранение старого пре-байта
Rx_Pre = data_byte; //обновление пре-байта
if(Pre == FESC) //если пре-байт равен FESC,
{
if(data_byte == TFESC) //а байт данных равен TFESC,
data_byte = FESC; //то заменить его на FESC
else if(data_byte == TFEND) //если байт данных равен TFEND,
data_byte = FEND; //то заменить его на FEND
else
{
Rx_Sta = WAIT_FEND; //для всех других значений байта данных,
Command = CMD_ERR; //следующего за FESC, ошибка
return;
}
}
else
{
if(data_byte == FESC) //если байт данных равен FESC, он просто
return; //запоминается в пре-байте
}
switch(Rx_Sta)
{
case WAIT_ADDR: //-----> ожидание приема адреса
{
if(data_byte & 0x80) //если бит 7 данных не равен нулю, то это адрес
{
data_byte = data_byte & 0x7F; //обнуляем бит 7, получаем истинный адрес
if(data_byte == 0 || data_byte == Rx_Add) //если нулевой или верный адрес,
{
Do_Crc8(data_byte, &Rx_Crc); //то обновление CRC и
Rx_Sta = WAIT_CMD; //переходим к приему команды
break;
}
Rx_Sta = WAIT_FEND; //адрес не совпал, ожидание нового пакета
break;
} //если бит 7 данных равен нулю, то
Rx_Sta = WAIT_CMD; //сразу переходим к приему команды
}
case WAIT_CMD: //-----> ожидание приема команды
{
if(data_byte & 0x80) //проверка бита 7 данных
{
Rx_Sta = WAIT_FEND; //если бит 7 не равен нулю,
Command = CMD_ERR; //то ошибка
break;
}
Rx_Cmd = data_byte; //сохранение команды
Do_Crc8(data_byte, &Rx_Crc); //обновление CRC
Rx_Sta = WAIT_NBT; //переходим к приему количества байт
break;
}
case WAIT_NBT: //-----> ожидание приема количества байт
{
if(data_byte > FRAME) //если количество байт > FRAME,
{
Rx_Sta = WAIT_FEND;
Command = CMD_ERR; //то ошибка
break;
}
Rx_Nbt = data_byte;
Do_Crc8(data_byte, &Rx_Crc); //обновление CRC
Rx_Ptr = 0; //обнуляем указатель данных
Rx_Sta = WAIT_DATA; //переходим к приему данных
break;
}
case WAIT_DATA: //-----> ожидание приема данных
{
if(Rx_Ptr < Rx_Nbt) //если не все данные приняты,
{
Rx_Dat[Rx_Ptr++] = data_byte; //то сохранение байта данных,
Do_Crc8(data_byte, &Rx_Crc); //обновление CRC
break;
}
if(data_byte != Rx_Crc) //если приняты все данные, то проверка CRC
{
Rx_Sta = WAIT_FEND; //если CRC не совпадает,
Command = CMD_ERR; //то ошибка
break;
}
Rx_Sta = WAIT_FEND; //прием пакета завершен,
Command = Rx_Cmd; //загрузка команды на выполнение
break;
}
}
}
//------------------ Прерывание UART после передачи байта: -------------------
ISR (USART_TXC_vect)
{
if(Tx_Sta == SEND_FEND) return; //ожидание передачи ответа
char data_byte;
if(Tx_Pre == FEND) //если производится стаффинг,
{
data_byte = TFEND; //передача TFEND вместо FEND
Tx_Pre = data_byte;
UDR = data_byte;
return;
}
if(Tx_Pre == FESC) //если производится стаффинг,
{
data_byte = TFESC; //передача TFESC вместо FESC
Tx_Pre = data_byte;
UDR = data_byte;
return;
}
switch(Tx_Sta)
{
case SEND_ADDR: //-----> передача адреса
{
if(Tx_Add) //если адрес не равен нулю,
{
data_byte = Tx_Add;
Do_Crc8(data_byte, &Tx_Crc); //то обновление CRC,
data_byte |= 0x80; //бит 7 адреса всегда равен единице
Tx_Pre = data_byte; //сохранение пре-байта
if(data_byte == FEND || data_byte == FESC)
data_byte = FESC; //передача FESC, если нужен стаффинг
UDR = data_byte;
Tx_Sta = SEND_CMD;
return;
}
else
Tx_Sta = SEND_CMD; //иначе сразу передаем команду
}
case SEND_CMD: //-----> передача команды
{
data_byte = Tx_Cmd & 0x7F;
Tx_Sta = SEND_NBT;
break;
}
case SEND_NBT: //-----> передача количества байт
{
data_byte = Tx_Nbt;
Tx_Sta = SEND_DATA;
Tx_Ptr = 0; //обнуление указателя данных для передачи
break;
}
case SEND_DATA: //-----> передача данных
{
if(Tx_Ptr < Tx_Nbt)
data_byte = Tx_Dat[Tx_Ptr++];
else
{
data_byte = Tx_Crc; //передача CRC
Tx_Sta = SEND_CRC;
}
break;
}
default:
{
#ifdef RS485
Port_DIR_0; //переключение RS-485 на прием
#endif
Tx_Sta = SEND_IDLE; //передача пакета завершена
return;
}
}
Do_Crc8(data_byte, &Tx_Crc); //обновление CRC
Tx_Pre = data_byte; //сохранение пре-байта
if(data_byte == FEND || data_byte == FESC)
data_byte = FESC; //передача FESC, если нужен стаффинг
UDR = data_byte;
}
//--------------------- Вычисление контрольной суммы: ------------------------
void Do_Crc8(unsigned char b, unsigned char *crc)
{
for(unsigned char i = 0; i < 8; b = b >> 1, i++)
if((b ^ *crc) & 1) *crc = ((*crc ^ 0x18) >> 1) | 0x80;
else *crc = (*crc >> 1) & ~0x80;
}
//------------------------ Запрос передачи пакета: ---------------------------
void Port_Tx_Frame(void)
{
#ifdef RS485
TxTimer = ms2sys(TX_DELAY); //если режим RS-485, то задержка ответа
#else
TxTimer = 0; //если режим RS-232, то нет задержки
#endif
Tx_Sta = SEND_FEND; //запрос начала передачи пакета
}
//------------------ Передача пакета с задержкой ответа: ---------------------
void Port_Tx_Exe(bool t)
{
if(Tx_Sta == SEND_FEND) //если есть запрос передачи
{
if(TxTimer == 0) //и задержка ответа истекла
{
unsigned char data_byte = FEND;
Tx_Crc = CRC_INIT; //инициализация CRC,
Do_Crc8(data_byte, &Tx_Crc); //обновление CRC
Tx_Sta = SEND_ADDR; //подготовка к передаче адреса
Tx_Pre = TFEND;
#ifdef RS485
Port_DIR_1; //переключение RS-485 на передачу
#endif
UDR = data_byte; //передача FEND
}
else
if(t) TxTimer--; //иначе декремент таймера
}
}


