- •Техническое задание
- •Реферат
- •Перечень условных обозначений, единиц и терминов
- •Содержание
- •Введение
- •1 Структурная организация
- •2 Алгоритмы обработки и управления
- •2.1 Алгоритм работы ведущего омк
- •2.2 Алгоритм работы ведомого омк
- •3 Выбор элементной базы
- •3.1 Выбор омк
- •3.2 Выбор пу
- •4 Принципиальная электрическая схема
- •5 Программное обеспечение
- •6 Алгоритм тестирования
- •7 Инструкция по эксплуатации контроллера
- •Заключение
- •Список использованных источников
- •Приложение а
- •Приложение б
- •Приложение в
Приложение б
Таблица 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)
{ }
}
