Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пояснительная записка_Мельников_6401.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
1.29 Mб
Скачать

Приложение б

Таблица 3 – Спецификация элементов

Позиционное обозначение

Наименование

Количество

Описание

MASTER, SLAVE1, SLAVE2, SLAVE3

ATmega48P

4

Однокристальный микроконтроллер

U3, U5, U7, U9

MAX487

4

Преобразователь уровней

D2

1

Зеленый светодиод

D3

1

Красный светодиод

C1-C2

2

Конденсатор

U2

1

Цифровой инвертор

X1

1

Внешний кварцевый генератор

Приложение в

Листинг программы ведущего ОМК

#include <stdio.h>

#include <mega48p.h>

#include <iobits.h>

#include <bcd.h>

#include <stdbool.h>

#include <stdlib.h>

// Глобальные переменные

#define DATA_REGISTER_EMPTY (1<<UDRE0)

#define RX_COMPLETE (1<<RXC0)

#define FRAMING_ERROR (1<<FE0)

#define PARITY_ERROR (1<<UPE0)

#define DATA_OVERRUN (1<<DOR0)

#define FRAME_MAX_LENGTH 10

#define SENSORS_COUNT 3

int i=0;

unsigned char frame[FRAME_MAX_LENGTH];//максимум: старт(1), адрес(1), КОп(1), A(3), B(3), финиш(1)

// старт(1), адрес(1), КОп(1), R(2), финиш(1)

//минимум: старт(1), адрес(1), КОп(1), финиш(1)

unsigned char cur_address = 0;

char frame_i; //текщий передаваемый элемент фрейма

bool need_config=true;

int data[SENSORS_COUNT];

#ifndef _DEBUG_TERMINAL_IO_

#define _ALTERNATE_GETCHAR_

#pragma used+

unsigned char getchar(void) {

unsigned char status,data;

while (1)

{

while (((status=UCSR0A) & RX_COMPLETE)==0);

data=UDR0;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

return data;

}

}

#pragma used-

#endif

void USART_Transmit( unsigned char data )

{

/* Wait for empty transmit buffer */

while ( !( UCSR0A & (1<<UDRE0)));

/* Copy 9th bit to TXB8 */

UCSR0B &= ~(1<<TXB80);

if ( frame_i<=1 ) UCSR0B |= (1<<TXB80);

/* Put data into buffer, sends the data */

UDR0 = data;

}

unsigned char check_leak(void)//возвращаем номер первой утечки, либо 0, если все ок.

{

unsigned char idx=0;

bool ok=true;

if(SENSORS_COUNT<2) return 0;

while(ok&&idx<SENSORS_COUNT-1)

{ if(data[idx]!=0)

{

if(((float)abs(data[idx]-data[idx+1])/data[idx])>0.01) ok=false;

} else if (data[idx]!=0)

{

if(((float)abs(data[idx]-data[idx+1])/data[idx+1])>0.01) ok=false;

}

idx++;

}

return ok?0:idx;

}

void clear_frame(void)

{ int i=0;

for(i=0;i<FRAME_MAX_LENGTH;i++) frame[i]=0;

}

void clear_data(void)

{ int i=0;

for(i=0;i<SENSORS_COUNT;i++) data[i]=0;

}

void transmit(bool is_config, int A, int B)

{

clear_frame();

frame[0]=0x0A; //старт

frame[1]=bin2bcd(cur_address);

if(is_config)

{

//т.к. A и B могут быть + и -, то для передачи переведем в uint, а при приеме - обратно

unsigned int AA=(unsigned int)A;

unsigned int BB=(unsigned int)B;

frame[2]=0x0C;

//старшими разрядами вперед

frame[3]=bin2bcd(AA/10000%100);

frame[4]=bin2bcd(AA/100%100);

frame[5]=bin2bcd(AA%100);

frame[6]=bin2bcd(BB/10000%100);

frame[7]=bin2bcd(BB/100%100);

frame[8]=bin2bcd(BB%100);

frame[9]=0x0F;

}

else

{

frame[2]=0x0B;//запрос

frame[3]=0x0F;

}

frame_i=0;

UCSR0B |= (1<<UDRIE0); //включаем прерывания пустого UDR0

}

void handle_frame(void)

{

int q;

frame_i=0;

//тут фрейм принимается полностью

if(frame[2]==0x0D)

{

q=bcd2bin(frame[3])*100+bcd2bin(frame[4]);

data[cur_address-1]=q; //здесь обновить значение в массиве

if(cur_address==SENSORS_COUNT)

{ //после получения всех значений

if(check_leak()>0)CLRBIT(PORTD,6) // проверить, нету ли утечки

else SETBIT(PORTD,6);

}

}

else if(frame[2]==0x0E){}

else if(frame[2]==0x0C){}

}

// Timer 0 overflow interrupt service routine

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{

SETBIT(PORTD,7);

cur_address=cur_address%SENSORS_COUNT+1;

transmit(need_config, 0,1);

if(need_config&&cur_address==SENSORS_COUNT) need_config=false;

}

interrupt [USART_DRE] void usert_data_register_empty(void) //срабатывает, пока регистр пуст и прерывание включено

{

USART_Transmit(frame[frame_i]);

if(frame[frame_i]==0x0F)

{

UCSR0B &= ~(1<<UDRIE0); //отключаем прерывания пустого UDR0

}

else frame_i++;

}

interrupt [USART_TXC] void usart_transfer_complete(void)

{

//если конец фрейма, перевести ПУ в режим приема if(frame[frame_i]==0x0F)

{

frame_i=0;

clear_frame();

CLRBIT(PORTD,7);

}

}

interrupt [USART_RXC] void usart_recieve_complete(void)

{

//прочитать, что получили

int k = UDR0;

frame[frame_i]=k;

if(k==0x0F)

{ //если конец фрейма, то перевести ПУ в режим передачи

SETBIT(PORTD,7);

//начать обработку принятого фрейма

handle_frame();

}

frame_i++;

}

void main(void)

{

// Crystal Oscillator division factor: 1

#pragma optsize-

CLKPR=(1<<CLKPCE);

CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);

#ifdef _OPTIMIZE_SIZE_

#pragma optsize+

#endif

// Input/Output Ports initialization

// Port D initialization

// Function: Bit7=Out Bit6=Out Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRD=(1<<DDD7) | (1<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);

// State: Bit7=1 Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTD=(1<<PORTD7) | (1<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// USART initialization

// Communication Parameters: 9 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART0 Mode: Asynchronous

// USART Baud Rate: 9600

// RX, TX interrupts enabled

UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);

UCSR0B=(1<<RXCIE0) | (1<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (1<<UCSZ02) | (0<<RXB80) | (0<<TXB80);

UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);

UBRR0H=0x00;

UBRR0L=0x33;

// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: 7,813 kHz

// Mode: Normal top=0xFF

// OC0A output: Disconnected

// OC0B output: Disconnected

// Timer Period: 32,768 ms

TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);

TCCR0B=(0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00);

TCNT0=0x00;

OCR0A=0x00;

OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization

TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);

clear_data();

// Global enable interrupts

#asm("sei")

while (1)

{

}

}

Листинг программы ведомых ОМК

// Standard Input/Output functions

#include <stdio.h>

#include <mega48p.h>

#include <iobits.h>

#include <bcd.h>

#include <stdbool.h>

#include <io.h>

#define DATA_REGISTER_EMPTY (1<<UDRE0)

#define RX_COMPLETE (1<<RXC0)

#define FRAMING_ERROR (1<<FE0)

#define PARITY_ERROR (1<<UPE0)

#define DATA_OVERRUN (1<<DOR0)

#define OUR_ADDRESS 3 //от 01 до 99

#define FRAME_MAX_LENGTH 10

unsigned char frame[FRAME_MAX_LENGTH];

char frame_i=0; //текущий элемент фрейма

eeprom int A=0;

eeprom int B=1;

float F=0;

int Q=111;

bool veracity=true;//флаг достоверности

unsigned int counter=0;

bool start_timer=false;

// Get a character from the USART Receiver

#ifndef _DEBUG_TERMINAL_IO_

#define _ALTERNATE_GETCHAR_

#pragma used+

char getchar(void)

{

char status,data;

while (1)

{

while (((status=UCSR0A) & RX_COMPLETE)==0);

data=UDR0;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

return data;

}

}

#pragma used-

#endif

// Write a character to the USART Transmitter

#ifndef _DEBUG_TERMINAL_IO_

#define _ALTERNATE_PUTCHAR_

#pragma used+

void putchar(char c)

{

while ((UCSR0A & DATA_REGISTER_EMPTY)==0);

UDR0=c;

}

#pragma used-

#endif

void transmit_frame(void)

{

frame_i=0;

UCSR0B |= (1<<UDRIE0); //включаем прерывания пустого UDR0

}

void USART_Transmit( unsigned char data )

{

/* Wait for empty transmit buffer */

while ( !( UCSR0A & (1<<UDRE0)));

/* Copy 9th bit to TXB8 */

UCSR0B &= ~(1<<TXB80);

if ( frame_i<=1 ) UCSR0B |= (1<<TXB80);

/* Put data into buffer, sends the data */

UDR0 = data;

}

void clean_frame(void)//на всякий случай

{

char i;

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

{

frame[i]=0;

}

}

void prepare_frame(char cmd)

{

clean_frame();

//0x0C - подтверждение конфига

//0x0E - данные недостоверны

//0x0D - результат измерений

frame[0]=0x0A;

frame[1]=0;

if(cmd==0x0C)

{

frame[2]=cmd;

frame[3]=0x0F;

}else if(cmd==0x0B)

{

if(veracity)

{

frame[2]=0x0D;

frame[3]=bin2bcd(Q/100%100);

frame[4]=bin2bcd(Q%100);

frame[5]=0x0F;

veracity = false;

}else

{

frame[2]=0x0E;

frame[3]=0x0F;

}

}

}

void handle_frame(void)

{

if(frame[2]==0x0C) //config

{

unsigned int AA = bcd2bin(frame[3])*10000+bcd2bin(frame[4])*100+bcd2bin(frame[5]);

unsigned int BB = bcd2bin(frame[6])*10000+bcd2bin(frame[7])*100+bcd2bin(frame[8]);

A=(signed int)AA;

B=(signed int)BB;

prepare_frame(0x0C);

transmit_frame();

}else if(frame[2]==0x0B)//request

{

prepare_frame(0x0B);

transmit_frame();

}

}

interrupt [USART_DRE] void usert_data_register_empty(void) //срабатывает, пока регистр пуст и прерывание включено

{

USART_Transmit(frame[frame_i]);

if(frame[frame_i]==0x0F) UCSR0B &= ~(1<<UDRIE0); //отключаем прерывания пустого UDR0

else frame_i++;

}

interrupt [USART_TXC] void usart_transfer_complete(void)

{

//если конец фрейма, перевести ПУ в режим приема и перейти обратно в режим многопроцессорной коммуникации (для ведомого)

if(frame[frame_i]==0x0F)

{

CLRBIT(PORTD,7);

UCSR0A |=(1<<MPCM0);

clean_frame();

}

}

interrupt [USART_RXC] void usart_recieve_complete(void)

{

//прочитать, что получили

char k = UDR0;

//если k=нашему адресу - выходим из многопроц режима

if(k==0x0A)

{

frame_i=0;

} else

if(bcd2bin(k)==OUR_ADDRESS&&frame_i==1)

{

UCSR0A &=~(1<<MPCM0);

// frame_i=1;

}

// else if(frame_i>0)

{

frame[frame_i]=k;

frame_i++;

}

//если конец фрейма, то перевести ПУ в режим передачи. Нет, во время начала передачи

if(k==0x0F)

{

SETBIT(PORTD,7);

//начать обработку принятого фрейма

//frame_i=0;

handle_frame();

}

}

// Timer1 input capture interrupt service routine

interrupt [TIM1_CAPT] void timer1_capt_isr(void)

{ unsigned int temp;

TCNT1H = 0;

TCNT1L = 0;

//TIM16_WriteTCNT1_Zero();

temp=ICR1L;

temp+= ICR1H<<8;

F=500000.0/temp;

Q=A+F*B;//A+F*B;

veracity=true;

}

void main(void)

{

// Declare your local variables here

char c;

// Crystal Oscillator division factor: 1

#pragma optsize-

CLKPR=(1<<CLKPCE);

CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);

#ifdef _OPTIMIZE_SIZE_

#pragma optsize+

#endif

// Port D initialization

// Function: Bit7=Out Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRD=(1<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);

// State: Bit7=0 Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// USART initialization

// Communication Parameters: 9 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART0 Mode: Asynchronous

// USART Baud Rate: 9600

// многопроцессорный режим

UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (1<<MPCM0);

UCSR0B=(1<<RXCIE0) | (1<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (1<<UCSZ02) | (0<<RXB80) | (0<<TXB80);

UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);

UBRR0H=0x00;

UBRR0L=0x19;

// Timer/Counter 1 initialization

// Mode: Normal top=0xFFFF

// OC1A output: Disconnected

// OC1B output: Disconnected

// Noise Canceler: Off

// Input Capture on Falling Edge

// Timer1 Overflow Interrupt: Off

// Input Capture Interrupt: Off

// Compare A Match Interrupt: Off

// Compare B Match Interrupt: Off

TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);

TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);

TCNT1H=0x00;

TCNT1L=0x00;

ICR1H=0x00;

ICR1L=0x00;

OCR1AH=0x00;

OCR1AL=0x00;

OCR1BH=0x00;

OCR1BL=0x00;

//// Timer/Counter 1 Interrupt(s) initialization

TIMSK1=(1<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);

// External Interrupt(s) initialization

// INT0: On

// INT0 Mode: Rising Edge

// INT1: Off

// Interrupt on any change on pins PCINT0-7: Off

// Interrupt on any change on pins PCINT8-14: Off

// Interrupt on any change on pins PCINT16-23: Off

EICRA=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (1<<ISC00);

EIMSK=(0<<INT1) | (1<<INT0);

EIFR=(0<<INTF1) | (1<<INTF0);

#asm("sei")

while (1)

{ }

}

30