- •Содержание
- •Техническое задание
- •Введение
- •Разработка алгоритма
- •Математический алгоритм
- •Разработка схем алгоритмов
- •2. Разработка программы
- •2.1 Разработка программы на пк.
- •2.2 Разработка программы на микроконтроллер.
- •Вычислительный эксперимент
- •3.1 Программа разработанная на языке с#.
- •4.3 Обращение к программе
- •Входные и выходные данные
- •Руководство пользователя
- •Заключение
- •Список литературы
- •Приложение а Текст программы на пк.
- •Приложение б Текст программы на микроконтоллер.
Приложение б Текст программы на микроконтоллер.
Текст программы файла 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 – Продолжение.