Разработка программного обеспечения
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

 

Листинг программы на языке C++ для микроконтроллера ATmega16:

 

//== Библиотеки ========================================

#include <mega16.h>

#include <delay.h>

#include "ctype.h"

#include "stdlib.h"

//== Global Variables =====================================

#define TRUE 1

#define FALSE 0

#define COM1 0x01//команда начала вычислении arCthZ

#define COM2 0x02 //команда начала вычислении arcsinZ

#define GICRMask 0xC0 //разрешение прерываний Int0 Int1

#define MCUCRMask 0xCF //спящий режим POWER Down прерывания по низкому уровню

#define nMCUCRMask 0x0F //запрет режима POWER Down

// биты для настройки SPI

#define MOSI 5 //выходный данные передаются по 5 биту порта В

#define SCK 7 // импульсы синхронизации передаются по 7 биту порта В

#define SS 4 //бит упарвляющий передачей данных

#define SPIE 7 //разрешение прерываний по SPI

#define SPE 6 // включение SPI

#define MSTR 4 //МК в режиме мастер

#define SPR0 0 // делитель на 16

#define CLRBIT(ADDR,BIT) (ADDR&=~(1<<BIT))

#define SETBIT(ADDR,BIT) (ADDR|=(1<<BIT))

unsigned char com;//переменная для хранения полученной команды

unsigned char DATA[4];//массив данных, в котором хранится полученное значение Z

unsigned char DATA_SEND[4];//массив данных, в котором хранится результат вычислений

unsigned char DDR_SPI; //переменная для настройки работы порта В

unsigned char SPIF = 0;//флаг завершения передачи/приема данных по SPI

unsigned char FlagInt1 = 0//флаг получения прерывания INT1 – вывод МК из спящего режима

unsigned char FlagInt0 = 0;//флаг получения прерывания INT0 – перевод МК в спящий режим

unsigned char FlagCalcReady = 0; //флаг завершения вычислений

//== Const =============================================

// Table of 2^(-i) ---------------------------------------------

float dva[15]={0.5,0.25,0.125,0.0625,0.03125,0.015625,

0.0078125,0.00390625,0.001953125,0.0009765625,

0.00048828125,0.000244140625, 0.0001220703125, 0.00006103515625,

0.00003051758125};

// Table of Arth -------------------------------------------------

loat ath[13]={ 0.5493061,0.2554128,0.1256572,0.0625816,0.0312602,0.0156263,

0.0078127,0.0039063, 0.0019531,0.0009766,0.0004883,0.0002441,

0.0001221 };

float log1[13]={0.5849625, 0.3219281,0.169925, 0.0874628, 0.0443941, 0.0223678,

0.0112273, 0.0056245, 0.0028150, 0.0014082, 0.0007043, 0.0003522,

0.0001761};

float log2[13]={1, 0.4150375, 0.1926451, 0.0931094, 0.0458037, 0.0227201, 0.0113153,

0.0056466, 0.0028205, 0.0014096, 0.0007046, 0.0003523, 0.0001761};

//=====================================================

void GlobalInitialize(void)

{

#asm ("cli");

DDRB = DDR_SPI;

PORTB = 0xD0;

DDRD = 0x00; //PortD as input

PORTD = 0x0C; //подключение резисторов подтяжки к выводам PD2, PD3

GICR=GICRMask;

MCUCR=nMCUCRMask;

#asm ("sei");

}

//=====================================================

void Init_SPI_SLAVE(void)

{

 //настройка интерфейса в режим подчиненный

 DDR_SPI=(1<<MOSI); //формируем маску для порта В: передача битов по MOSI

 //прием по MISO, тактовый сигнал и сигнал выбора МС на ввод

 

 SPCR |= (1 << SPIE); //разрешение прерывания по SPI

 SPCR |= (1 << SPE); //включение интерфейса

}

//== функция приема сообщений ============================

void SPI_SlaveReceive(void)

{

unsigned char i;

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

{

while(!(SPSR & (1<<SPIF))); //ждем завершения передачи 1-го байта

com = SPDR;

SPIF = FALSE;

}

for(i=1; i<5; i++)

{

while(!SPIF);  //ждем завершения передачи байта

DATA[i-1] = SPDR;

SPIF = FALSE;

}

}

//== функция передачи данных =============================

void SPI_SlaveSend(void)

{

unsigned char i;

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

{

SPDR = DATA_SEND[3-i]; //сохр данный в регистре данных SPI

while(!SPIF); //ждем завершения передачи

SPIF = FALSE; //установка флага завершения передачи в 0

}

FlagCalcReady = 0;

}

//====преобразования данных в формат с плавающей запятой =======

float char_to_Float(void)

{

float tmp=0;

float a=255;

tmp = (DATA[3]*a);//преобразование целой части

tmp=tmp+DATA[2];

tmp=tmp+(DATA[1]/a);//преобразование дробной части

tmp=tmp +(DATA[0]/a/a);

return tmp;

}

//=====================================================

void Float_to_char(float tmp)

{

int data_tmp=0;

data_tmp=(int)tmp;

DATA_SEND[3]=data_tmp>>8;

DATA_SEND[2]=data_tmp;

data_tmp=(int)((tmp-data_tmp)*65025);

DATA_SEND[1]=data_tmp>>8;

DATA_SEND[0]=data_tmp;

}

//=====================================================

float arCth(float Z)

{

float aCh;

float X0=1.45235,X1=0,Y0=0,Y1=0,Q0=0,Q1=0;

unsigned char i,n;

for(n=1;n<=26;n++)//число итераций 26

{

i = 1 +((n-1)>>1);

if ((Z-Q0)>=0) //определение знака итерации

{

Q1=Q0 + ath[i-1];  //вычисление Z

X1=X0 + Y0*dva[i-1]; //вычисление Xi=arcthZ

Y1=Y0 + X0*dva[i-1]; //вычисление Yi=sh(arChZ)

}

else

{

Q1=Q0 - ath[i-1]; //вычисление Z

X1=X0 - Y0*dva[i-1];//вычисление Xi=arcthZ

Y1=Y0 - X0*dva[i-1]; //вычисление Yi=sh(arChZ)

}

//сохранение предыдущих значений

Q0=Q1;

X0=X1;

Y0=Y1;

}

aCh = Q1;

FlagCalcReady = 1;

return aCh;

}

//=====================================================

float arcsinZ (float Z)

{

float as;

float X0=1.0, X1=0.0, Q0=0.0, Q1=0.0;

unsigned char i,n;

for(n=1;n<=26;n++)

{

i = 1 + ((n-1)>>1);

if ((Z-Q0)>=0) //определение знака итерации

{

Q1=Q0 + log1[i]; //вычисление угла

X1=X0 + X0*dva[i]; //вычисление Xi

}

else

{

Q1=Q0 - log2[i]; //вычисление Z

X1=X0 - X0*dva[i]; //вычисление Xi

}

Q0=Q1;

X0=X1;

}

as = X1;

FlagCalcReady =1;

return as;

}

//=====================================================

void main(void)

{

unsigned char nSS; //сигнал выбора микросхемы

float Z, ans;

Init_SPI_SLAVE(); //инициализация SPI

GlobalInitialize(); //настройка портов ввода-вывода

while(1)

{

if (FlagInt0) //обработка прерывания Инт0

{

FlagInt0=0;

MCUCR=MCUCRMask; //разрешение включения спящего режима

#asm ("SLEEP");} //переход в спящий режим

}

if (FlagInt1)

{

FlagInt1=0;

nSS = PORTB & 0x10; //маска для выделения бита PORTB4

if (nSS == 0)

{

SPI_SlaveReceive();

if (com == COM1)

{

Z = char_to_Float();

ans = arCth(Z);

}

if (com == COM2)

{

Z = char_to_Float();

ans = arcsin (Z );

}

}

if (FlagCalcReady)

{

Float_to_char(ans);

SPI_SlaveSend();

}

}

}

//=interrupt==============================================

interrupt [EXT_INT0] void INT0_interrupt(void) //обработка прерывания Int0

{

FlagInt0 = 1; //установка флага

}

interrupt [EXT_INT1] void INT1_interrupt(void) //обработка прерывания Int1

{

FlagInt1 = 1; //установка флага

MCUCR=nMCUCRMask; //запрет спящего режима

}

 



Дата: 2019-05-28, просмотров: 170.