Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсовик ЭВМиВС мой.doc
Скачиваний:
2
Добавлен:
15.09.2019
Размер:
2.63 Mб
Скачать

Приложение б Текст программы на микроконтоллер.

Текст программы файла Neyro.h представлен на рисунке Б.1.

#include "stm32f4xx.h"

#define Amount_Vvod 10 //количество входных значений

#define Neyr1 4 //количество нейронов первого слоя

#define Neyr2 2 //количество нейронов второго слоя

typedef struct

{

double vvod[Amount_Vvod]; //массив входных значений

double prom[Neyr1]; //массив выходов первого слоя

double rez[Neyr2]; //массив выходов второго слоя

double w1[Amount_Vvod][Neyr1]; //веса нейронов первого слоя

double w2[Neyr1][Neyr2]; //веса нейронов второго слоя

double k; //коэфициент сигмоиды

double skor; //коэффициент скорости обучения

int ogid1[Neyr2]; //функция ожидания для 1 класса

int ogid2[Neyr2]; //функция ожидания для 2 класса

}Neyro;

void Res(Neyro* nr);

void CreateNeyro(Neyro* nr);

Рисунок Б.1 – Текст программы файла Neyro.h.

Текст программы файла Neyro.с представлен на рисунке Б.2.

#include "Neyro.h"

#include <stdlib.h>

#include <math.h>

#include <time.h>

void CreateNeyro(Neyro* nr)

{

char i=0, j=0;

//srand(time(NULL));

//Заполнение матрицы весовых коэффициентов w1

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

{

for (j = 0; j < Neyr1; j++)

{

nr->w1[i][j] = (double)(rand()%3)-0.5;

}

}

//Заполнение матрицы весовых коэффициентов w2

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

Рисунок Б.2 – Текст программы файла Neyro.с.

Продолжение приложения Б

{

for (j = 0; j < Neyr2; j++)

{

nr->w2[i][j] = (double)(rand()%3)-0.5;

}

}

nr->ogid1[0] = 0;

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

{

if (nr->ogid1[i - 1] == 0)

nr->ogid1[i] = 1;

else nr->ogid1[i] = 0;

}

nr->ogid2[0] = 1;

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

{

if (nr->ogid2[i - 1] == 0)

nr->ogid2[i] = 1;

else nr->ogid2[i] = 0;

}

}

void Res(Neyro* nr)

{

double sum = 0;

char n=0,i=0;

for (n = 0; n < Neyr1; n++)

{

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

{

sum = sum + (nr->vvod[i] * nr->w1[i][n]);

}

nr->prom[n] = 1 / (1 + exp((-sum)*nr->k));

sum=0;

}

sum=0;

for (n = 0; n < Neyr2; n++)

{

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

{

sum = sum + (nr->prom[i] * nr->w2[i][n]);

}

nr->rez[n] = 1 / (1 + exp((-sum)*nr->k));

sum=0;

}

}

Рисунок Б.2 – Продолжение.

Продолжение приложения Б

Текст программы файла main.с представлен на рисунке Б.3.

#include "stm32f4xx.h"

#include "stm32f4_discovery.h"

#include "Neyro.h"

#include <stdlib.h>

#define NOM 15 //количество принимаемых байт через UART

char bufer[NOM]; //буфер для приема через COM

volatile char flag_uart=0; //флаг для уарт, если 1 то принята инфа

volatile uint64_t timeout=0; //таймаут для уарт

volatile int count_bufer=0; //счетчик элементов буфера уарт

volatile int flag_koef=0; //когда =1 принимаем коэффициенты матриц

volatile int flag_chisla=0; //когда =1 принимаем числа

double buf_koef[(10*Neyr1)+(Neyr1*Neyr2)]; //преобразованные коэффициенты

double buf_chisla[Amount_Vvod]; //преобразованные числа

Neyro nr;

volatile int delay_time=0; //переменная для задержки

//////////////////////////////////////////////////////////////////////////

//задержка в милисекундах, работает через таймер SysTick

void delay(int n)

{

delay_time=n;

while(delay_time != 0);

}

/////////////////////////////////////////////////////////////////////.....

// Инициализация УАРТа

//////////////////////////////////////////////////////////////////////////

void InitUart4(void)

{

GPIO_InitTypeDef GPIO_uart;

USART_InitTypeDef USART_InitStructure;

//USART_ClockInitTypeDef USART_ClockInitStructure;

//enable bus clocks

RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

//Set UART4 Tx (PC.10) as AF push-pull

GPIO_uart.GPIO_Pin = GPIO_Pin_10;

GPIO_uart.GPIO_Mode = GPIO_Mode_AF;

GPIO_uart.GPIO_OType = GPIO_OType_PP;

GPIO_uart.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_uart);

//Set UART4 Rx (PC.11) as input floating

GPIO_uart.GPIO_Pin = GPIO_Pin_11;

Рисунок Б.3 – Текст программы файла main.с.

Продолжение приложения Б

GPIO_uart.GPIO_Mode = GPIO_Mode_AF;

GPIO_uart.GPIO_OType = GPIO_OType_PP;

GPIO_uart.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_uart.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_uart);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_UART4);

//USART_ClockStructInit(&USART_ClockInitStructure);

//USART_ClockInit(UART4, &USART_ClockInitStructure);

USART_InitStructure.USART_BaudRate = 9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No ;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

//Write UART4 parameters

USART_Init(UART4, &USART_InitStructure);

//разрешение прерывания по приему данных

USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);

NVIC_EnableIRQ(UART4_IRQn); //вкл прерывание

//USART_ITConfig(UART4, USART_IT_TXE, DISABLE);

//Enable USART4

USART_Cmd(UART4, ENABLE);

}

//////////////////////////////////////////////////////////////////////

// Инициализация портов

//////////////////////////////////////////////////////////////////////////

void InitPorts()

{

GPIO_InitTypeDef gpiod;

GPIO_InitTypeDef gpioa;

//тактирование порта D, A

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

//настройка порта D на выход

gpiod.GPIO_Mode = GPIO_Mode_OUT;

gpiod.GPIO_OType = GPIO_OType_PP;

gpiod.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

gpiod.GPIO_Speed = GPIO_Speed_50MHz;

// Инициализируем GPIO на порту D

//GPIO_DeInit(GPIOD);

GPIO_Init(GPIOD, &gpiod);

//настройка порта А на вход, используется кнопка подключенная к земле и к контроллеру

gpioa.GPIO_Mode = GPIO_Mode_IN;

gpioa.GPIO_OType = GPIO_OType_PP;

Рисунок Б.3 – Продолжение.

Продолжение приложения Б

gpioa.GPIO_Pin = GPIO_Pin_0;

gpioa.GPIO_Speed = GPIO_Speed_50MHz;

// Инициализируем GPIO на порту A

//GPIO_DeInit(GPIOA);

GPIO_Init(GPIOA, &gpioa);

}

///////////////////////////////////////////////////////////////////////////

// Прерывание УАРТа

//////////////////////////////////////////////////////////////////////////

void UART4_IRQHandler()

{

timeout=0;

if(flag_uart==1)

{

return; //если буфер не обработан, то выходим

}

//записываем принятое значение в буфер

bufer[count_bufer] = USART_ReceiveData(UART4);

// если приняли w, значит идете передача весовых коэф-ов

if(bufer[count_bufer] == 'w')

{

flag_koef=1;

return;

}

// если приняли c, значит идете передача чисел на распознавание

if(bufer[count_bufer] == 'c')

{

flag_chisla=1;

return;

}

if(bufer[count_bufer] == ',')

{

bufer[count_bufer] = '.';

}

//максимум NOM байт, если счетчик равен NOM, значит приняли все полностью

count_bufer++;

if(count_bufer==NOM)

{

count_bufer=0;

flag_uart=1;

}

}

//////////////////////////////////////////////////////////////////////////

// Обработчик прерывания по переполнению таймера SysTick

//////////////////////////////////////////////////////////////////////////

void SysTick_Handler()

{

static int i=0;

int srav=500;

Рисунок Б.3 – Продолжение.

Продолжение приложения Б

i++;

if(flag_koef==1 || flag_chisla==1)

{

srav=100;

if(i>100)

{

i=0;

}

}

if(flag_koef==0 && flag_chisla==0)

{

srav=500;

}

if(i==srav)

{

// Мигание светодиодом

GPIO_ToggleBits(GPIOD, GPIO_Pin_15);

i=0;

}

//если задана задержка delay

if(delay_time != 0)

{

delay_time--;

}

//если что то приняли, ждем таймаут

if(count_bufer != 0)

{

timeout++;

//если таймаут вышел, значит больше ничего не придет

if(timeout>30)

{

count_bufer=0;

flag_uart=1;

timeout=0;

}

}

}

//////////////////////////////////////////////////////////////////////////

void InitNeyro()

{

nr.k=1.3;

nr.skor=0.7;

CreateNeyro(&nr);

}

//////////////////////////////////////////////////////////////////////////

// Функция записы коэффициентов в матрицы

//////////////////////////////////////////////////////////////////////////

void Write_koef(Neyro* nr, const double *buf)

{

int i,j;

//Заполнение матрицы весовых коэффициентов w1

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

{

Рисунок Б.3 – Продолжение.

Продолжение приложения Б

for (j = 0; j < Neyr1; j++)

{

nr->w1[i][j] = *buf++;

}

}

//Заполнение матрицы весовых коэффициентов w2

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

{

for (j = 0; j < Neyr2; j++)

{

nr->w2[i][j] = *buf++;

}

}

}

//////////////////////////////////////////////////////////////////////////

// Функция записы коэффициентов в матрицы

//////////////////////////////////////////////////////////////////////////

void Write_vvod(Neyro* nr, const double *buf)

{

int i;

//заполнение массива входных значений

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

{

nr->vvod[i]=*buf/10;

buf++;

}

}

void Klass(Neyro* nr)

{

int i;

int znach[Neyr2];

int kl=0;

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

{

if (nr->rez[i] < 0.5)

{

znach[i] = 0;

}

if (nr->rez[i] > 0.5)

{

znach[i] = 1;

}

}

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

{

if (znach[i] == nr->ogid1[i])

{}

else goto m;

}

kl = 1;

m:

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

{

Рисунок Б.3 – Продолжение.

Продолжение приложения Б

if (znach[i] == nr->ogid2[i])

{}

else goto m1;

}

kl = 2;

m1:

if (kl == 0)

{

//вкл-выкл светодиодами

GPIO_SetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

delay(100);

GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

}

if (kl == 1)

{

GPIO_SetBits(GPIOD, GPIO_Pin_12);

}

if (kl == 2)

{

GPIO_SetBits(GPIOD, GPIO_Pin_14);

}

}

//////////////////////////////////////////////////////////////////////////

int main(void)

{

int i=0;

int cnt=0;

i=sizeof(double);

InitPorts();

InitUart4();

InitNeyro();

// Конфигурируем таймер SysTick на срабатывание 1000 раз в секунду

SysTick_Config(SystemCoreClock / 1000);

while(1)

{

//если приняты данные через уарт

if(flag_uart==1)

{

//если принимаем коэффициенты

if(flag_koef==1)

{

buf_koef[cnt]=atof(bufer);

cnt++;

//если приняли все коэффициенты

if(cnt == (10*Neyr1)+(Neyr1*Neyr2) )

{

cnt=0;

flag_koef=0;

Рисунок Б.3 – Продолжение.

Продолжение приложения Б

//записываем в матрицы

Write_koef(&nr,&buf_koef[0]);

//вкл-выкл светодиодами

GPIO_SetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

delay(200);

GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

}

}

//если принимаем числа

if(flag_chisla==1)

{

buf_chisla[cnt]=atof(bufer);

cnt++;

//если приняли все числа

if(cnt==Amount_Vvod)

{

cnt=0;

flag_chisla=0;

GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_14);

delay(200);

//записываем в массив входных значений

Write_vvod(&nr,&buf_chisla[0]);

Res(&nr);

Klass(&nr);

}

}

//обнуление буфера

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

{

bufer[i]=0;

}

flag_uart=0; //снимаем флаг уарта

}

}

}

Рисунок Б.3 – Продолжение.

51