ЦУМП II ARM Lab3 Тексты программ


Чтобы посмотреть этот PDF файл с форматированием и разметкой, скачайте его и откройте на своем компьютере.
Д
и49и20ин
а

«
Ци731вые 64531й45ва и ми#31
2319е4413ы»

Лаб13а513ная 3аб15а №
3

П
319е4413
ы 4 яд31м
ARM

Cortex
-
M
4
.

Ана01г1
-
9и731вые 2е3и7е3ийные 64531й45ва
.

И481дные 5е#45ы 231г3амм

и 149и001г3аммы

Общие м1д60и д0я 3аб15ы 4 АЦПL ЦАПL #1де#1м


Исходный модуль
a
dc.c

/**


******************************************************************************


* Файл adcŜc


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ0


* Описаниеś Функции инициализации и обслуживания АЦП


*


* Формат цифровых данных от АЦП
-

12
-
разрядный смещенный кодś


* код 1111 1111 1111 соответствует Uвх = максимум (практически Vref)Ś


* код 1000 0000 0000 соответствует Uвх = Vref / 2Ś


* код 0000 0000 0000 соответствует Uвх = минимум (практически 0)Ś


* где Vref
-

опорное н
апряжение (для отладочной платы равно напряжению питания)


*


* Сигналы запуска АЦПś выходы таймеров TIM1ř TIM2ř TIM3ř TIM4ř TIM5ř TIM8Ś


* внешний сигналаŜ


*


* Распределение аналоговых входов по разрядам портов и источникамś


* Порт ADC

Channel


* PA0 1,2,3 0


* PA1 1,2,3 1


* PA2 1,2,3 2


* PA3 1,2,3 3


* PA4 1,2 4


* PA5 1,2 5


* PA6 1,2 6


* PA7 1,2 7


* PB0 1,2 8


* PB1

1,2 9


* PC0 1,2,3 10


* PC1 1,2,3 11


* PC2 1,2,3 12


* PC3 1,2,3 13


* PC4 1,2 14


* PC5 1,2 15


* PF3 3 9


* PF4 3 14


* PF5 3 15



* PF6 3 4


* PF7 3 5


* PF8 3 6


* PF9 3 7


* PF10 3 8


*
-

1

16 (внутренний температурный датчик)


*
-

1 17 (опорное напряжение Vref внутреннего источника)


*
-

1 18 (напряжение батареи Vbat)


*


* ПримечанияŜ


* 1Ŝ Значение температуры с температурного датчика вычис
ляется по формулеś


* Температура в °C = {(VSENSE


V25) / Avg_Slope} + 25,


* где VSENSE
-

измеренное напряжение с датчикаŚ


* V25
-

напряжение с датчика при 25°Cř для STM32F407 равно 0Ŝ76 ВŚ


* Avg_Slope
-

температурны
й коэффициентř для STM32F407 равен 2Ŝ5 мВ/°CŜ


* Время преобразования АЦП должно быть не менее 10 мксŜ


* 2Ŝ На входе канала измерения напряжения батареи включен резистивный делитель на 2Ŝ


* 3Ŝ Для измерений по внутренним каналам небходимо доп
олнительно вызывать функции


* ADC_TempSensorVrefintCmd(ENABLE) или ADC_VBATCmd(ENABLE)Ŝ


*


******************************************************************************


*/


#include "stm32_p407.h"
//Файл конфигурации о
тладочной платы STM32
-
P407

#include "adc.h"
//Функции для работы с АЦП


//
---------------------------------------------------------------------------

// ИНИЦИАЛИЗАЦИЯ АЦП

// Входные аргументы функцииś

// ADCx
-

указатель на

объектś ADC1ř ADC2ř ADC3

// ADC_Channel
-

номер каналаś ADC_Channel_0ŜŜŜADC_Channel_18

// ADC_ExternalTrigConv
-

источник запускаř одна из следущих константś

// ADC_ExternalTrigConv_T1_CC1

// ADC_ExternalTrigConv_T1_CC2

// ADC_ExternalTrig
Conv_T1_CC3

// ADC_ExternalTrigConv_T2_CC2

// ADC_ExternalTrigConv_T2_CC3

// ADC_ExternalTrigConv_T2_CC4

// ADC_ExternalTrigConv_T2_TRGO

// ADC_ExternalTrigConv_T3_CC1

// ADC_ExternalTrigConv_T3_TRGO

// ADC_ExternalTrigConv_T5_C
C1

// ADC_ExternalTrigConv_T5_CC2

// ADC_ExternalTrigConv_T5_CC3

// ADC_ExternalTrigConv_T8_CC1

// ADC_ExternalTrigConv_T8_TRGO

// ADC_ExternalTrigConv_Ext_IT11

// Если соответствующий источник не сконфигурирован для запускаř аргумент может быть любойř напримерř 0ř

// в этом случае запуск осуществляется программно
-

вызовом функции ADC_SoftwareStartConvŜ

//

void ADC_Initialize(ADC_TypeDef* ADCx, uint8_t ADC_Ch
annel, uint32_t ADC_ExternalTrigConv)

{


ADC_CommonInitTypeDef ADC_CommonInitStruct;
//Структура общей конфигурации АЦП


ADC_InitTypeDef ADC_InitStructure;
//Структура конфигурации АЦП


GPIO_InitTypeDef GPIO_InitStructure;
//Структ
ура конфигурации портов общего назначения


GPIO_TypeDef* GPIO_Port;
//Указатель на базовый адрес порта


uint32_t RCC_AHB1Periph;
//Параметр для разрешения тактирования порта


uint16_t GPIO_Pin;

//Маска на разряд порта


uint8_t flag_port = 1;
//Признак использования разряда порта как входного




//Сопоставление номеров АЦП и каналов разрядам портов


switch (ADC_Channel)


{


case 0: RCC_AHB1Periph = RCC_AHB
1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_0; break;


case 1: RCC_AHB1Periph = RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_1; break;


case 2: RCC_AHB1Periph = RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_
2; break;


case 3: RCC_AHB1Periph = RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_3; break;


case 4: if (ADCx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_6;


else RCC_AHB1Periph

= RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_4;


break;


case 5: if (ADCx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_7;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOA,
GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_5;


break;


case 6: if (ADCx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_8;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_P
in = GPIO_Pin_6;


break;


case 7: if (ADCx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_9;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOA, GPIO_Port = GPIOA, GPIO_Pin = GPIO_Pin_7;



break;


case 8: if (ADCx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_10;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOB, GPIO_Port = GPIOB, GPIO_Pin = GPIO_Pin_0;


break;


case 9:

RCC_AHB1Periph = RCC_AHB1Periph_GPIOB, GPIO_Port = GPIOB, GPIO_Pin = GPIO_Pin_1; break;


case 10: RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GPIOC, GPIO_Pin = GPIO_Pin_0; break;


case 11: RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GP
IOC, GPIO_Pin = GPIO_Pin_1; break;


case 12: RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GPIOC, GPIO_Pin = GPIO_Pin_2; break;


case 13: RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GPIOC, GPIO_Pin = GPIO_Pin_3; break;


case 14: if (AD
Cx == ADC3) RCC_AHB1Periph = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_4;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GPIOC, GPIO_Pin = GPIO_Pin_4;


break;


case 15: if (ADCx == ADC3) RCC_AHB1Perip
h = RCC_AHB1Periph_GPIOF, GPIO_Port = GPIOF, GPIO_Pin = GPIO_Pin_5;


else RCC_AHB1Periph = RCC_AHB1Periph_GPIOC, GPIO_Port = GPIOC, GPIO_Pin = GPIO_Pin_5;


break;


default: flag_port = 0;


}




//Конфигурирование разряда порта как аналогового входа


if (flag_port)


{ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph, ENABLE);
//Разрешение тактирования порта


GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
//Номер разряда (маска)


GPIO_I
nitStructure.GPIO_Mode = GPIO_Mode_AIN;
//Альтернативная функцияś аналоговый вход


GPIO_Init(GPIO_Port, &GPIO_InitStructure);
//Функция конфигурирования


}



//Разрешение тактирования АЦП


if (ADCx == ADC1) RCC_APB2PeriphClockCmd(R
CC_APB2Periph_ADC1, ENABLE);


if (ADCx == ADC2) RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);


if (ADCx == ADC3) RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);



//Задание общей конфигурации АЦП по умолчаниюś


//
-

режим одиночного АЦПŚ


//
-

предварительный делитель тактовой частоты на 2Ś


//
-

запрет режима прямого доступа к памяти при совместной работе АЦПŚ


//
-

сдвиг между преобразованиями при совместной работе
-

5 тактовŜ


ADC_CommonStructInit(&ADC_CommonInitStruct);


ADC_CommonI
nit(&ADC_CommonInitStruct);




//Конфигурирование АЦП


ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
//Разрядность преобразованияś 12 (возможно 10ř 8ř 6)


ADC_InitStructure.ADC_ScanConvMode = DISABLE;
//Мног
оканальное сканированиеś не разрешено


ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//Непрерывное преобразованиеś запрещено


ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
//Фронт сигнала запуска


ADC_InitStruct
ure.ADC_ExternalTrigConv = ADC_ExternalTrigConv;
//Источник запуска


ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
//Выравнивание кода в 16
-
разрядном полеś влево


ADC_InitStructure.ADC_NbrOfConversion = 1;
//Число ка
налов для преобразованияś 1


ADC_Init(ADCx, &ADC_InitStructure);
//Функция конфигурирования



//Дополнительные параметры для АЦПś


//
-

номер входного каналаř


//
-

число групп преобразования
-

1 (возможно до 16 групп)ř


//
-

время

преобразования
-

56 тактов (возможные значенияś 3ř 15ř 28ř 56ř 84ř 112ř 144ř 480)





//Разрешение работы АЦП


ADC_Cmd(ADCx, ENABLE);

}



Заголовочный

модуль
adc.h

/**


**********
********************************************************************


* Файл adcŜh


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ0


* Описаниеś Функции инициализации и обслуживания АЦП


**********************************************************
********************


*/


#ifndef _ADC_H

#define _ADC_H


/* Объявления функций для их использования в других программных модулях */

void ADC_Initialize(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint32_t ADC_ExternalTrigConv);


//
---------------------------
------------------------------------------------

#endif
/* _ADC_H */



Исходный модуль
dac.c

/**


******************************************************************************


* Файл dacŜc


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ1


* Оп
исаниеś Функции инициализации и обслуживания ЦАП


*


* ЦАП может быть сконфигурирован для запуска от таймеров


* TIM2ř TIM4ř TIM5ř TIM6ř TIM7 соответствующей коррекцией в файле dacŜh


* (другие источники
-

EXTI Line9, TIM8
-

требуют более сложной
модификации)


*


* Формат данных для ЦАП
-

12
-
разрядный смещенный кодś


* код 1111 1111 1111 соответствует Uвых = максимум (практически Vref)Ś


* код 1000 0000 0000 соответствует Uвых = Vref / 2Ś


* код 0000 0000 0000 соответствует U
вых = минимум (практически 0)Ś


* где Vref
-

опорное напряжение (для отладочной платы равно напряжению питания)


*


******************************************************************************


*/


#include "stm32_p407.h"
//Файл кон
фигурации отладочной платы STM32
-
P407

#include "dac.h"
//Константы и функции для работы с ЦАП


//#define USE_DAC2 //Определение для использования второго канала ЦАПř


//режи
м возможенř если не используется графический дисплей


void DACTimerConfig(uint32_t SamplingFreq);

void DACConfig(uint32_t DAC_Trigger);


//
---------------------------------------------------------------------------

// ИНИЦИАЛИЗАЦИЯ ЦАП И СИСТЕМЫ ТАКТИРОВАН
ИЯ

// Входной параметр
-

частота дискретизации в ГцŚ если задано нулевое значениеř

// то синхронизация не используетсяř запуск ЦАП производится программно
-

// вызовом функции DAC_SetChannel1Data или DAC_SetChannel2Data

void DACInit(uint32_t SamplingFreq)

{


if (SamplingFreq)


{


//Инициализация таймера
-

источника тактирования ЦАП


DACTimerConfig(SamplingFreq);



//Инициализация ЦАП с запуском от таймера


DACConfig(DAC_Trigger_TD_TRGO);




//Разрешение прерываний от таймера


//DACTim
erInterruptConfig(ENABLE);


}


//Если не задана частота дискретизацииř инициализация ЦАП


// с режимом запуска по загрузке данных


else DACConfig(DAC_Trigger_None);

}


//
---------------------------------------------------------------------------

// И
НИЦИАЛИЗАЦИЯ ТАЙМЕРА ДЛЯ ТАКТИРОВАНИЯ ЦАП

/* Подпрограмма используется для таймеров TIM2ř TIM4ř TIM5ř TIM6ř TIM7ř


подключенных к шине APB1Ŝ По умолчанию частота работы шины 42 МГцř


частота тактирования таймеров этой шины
-

84 МГцŜ


При отсутствии п
редделения максимальный коэффициент деления для 16
-
разрядного


таймера равен 65536ř тŜеŜ минимальная частота дискретизации для этого случая


84000000 Гц / 65536 = 1282 ГцŜ


Для меньших значений частот необходимо предделение или применение 32
-
разрядно
го таймераŜ


В настоящей подпрограмме для частоты дискретизации SamplingFreqř заданной в Гцś


-

если предделитель не используется (его коэфŜ деления = 1)ř


числоř загружаемое в счетчикś TIM_Period = 84000000[Гц] / SamplingFreq[Гц]
-

1;


-

если коэффициент предделителя равен 1000ř


числоř загружаемое в счетчикś TIM_Period = 84000[Гц] / SamplingFreq[Гц]
-

1;


Для еще более низких частот (< 2 Гц)ř а также повышения точности необходимо


выбирать 32
-
разрядный таймер (TIM2ř TIM5)Ŝ


Прерывания от таймера конфигурируются по событию его автоперезагрузкиŜ

*/

void DACTimerConfig(uint32_t SamplingFreq)

{


//Структура конфигурации базового таймера


TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;



//Разрешение тактирования таймера


RC
C_APB1PeriphClockCmd(RCC_APB1Periph_TIMD, ENABLE);



//Базовая конфигурация таймера


if (SamplingFreq� 1300)


{ TIM_TimeBaseStructure.TIM_Period = 84000000u/SamplingFreq
-
1;
//Основной коэфŜделения


TIM_TimeBaseStructure.TIM_Prescaler = 0;

//Предделение не используется


}


else


{ TIM_TimeBaseStructure.TIM_Period = 84000u/SamplingFreq
-
1;
//Основной коэфŜделения


TIM_TimeBaseStructure.TIM_Prescaler = 1000
-
1;
//Предделитель в 1000 раз


}


TIM_TimeBaseStructure.TIM
_ClockDivision = 0;
//Делитель для входного фильтра


TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//Счетчик вверхś от 0 до TIM_Period


TIM_TimeBaseInit(TIMD, &TIM_TimeBaseStructure);
//Функция конфигурирования




//Активизация триггерного выхода TRGO таймера для запуска ЦАП


TIM_SelectOutputTrigger(TIMD, TIM_TRGOSource_Update);



//Разрешение прерываний при перезагрузке таймера


TIM_ITConfig(TIMD, TIM_IT_Update, ENABLE);




//Общее разрешение работы тайме
ра


TIM_Cmd(TIMD, ENABLE);

}


//
---------------------------------------------------------------------------

// ИНИЦИАЛИЗАЦИЯ ЦАП

// Используются DAC1 с выходом на разряд порта PA4

// и DAC2 с выходом на разряд порта PA5

// Входной параметрś ист
очник запуска ЦАП
-

одна из предопределенных константś

// DAC_Trigger_None, DAC_Trigger_T2_TRGO, DAC_Trigger_T4_TRGO, DAC_Trigger_T5_TRGO,

// DAC_Trigger_T6_TRGO, DAC_Trigger_T7_TRGO, DAC_Trigger_T8_TRGO, DAC_Trigger_Ext_IT9,

// DAC_Trigger_Software

voi
d DACConfig(uint32_t DAC_Trigger)

{


GPIO_InitTypeDef GPIO_InitStructure;
//Структура конфигурации портов общего назначения


DAC_InitTypeDef DAC_InitStructure;
//Структура конфигурации ЦАП



//Разрешение тактирования порта PAř ра
зряды которого используются как выходы ЦАП


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);



//Разрешение тактирования ЦАП


RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);



//Конфигурирование разрядов PAŜ4 (PAŜ5) как аналоговых

#ifdef USE_D
AC2


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
//Номера разрядов (маски) для DAC1ř DAC2

#else


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
//Номер разряда (маска) для DAC1

#endif


GPIO_InitStructure.GPIO_M
ode = GPIO_Mode_AN;
//Альтернат
.
функцияś аналоговый вход
-
выход


GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
//Без подтягивающих резисторов


GPIO_Init(GPIOA, &GPIO_InitStructure);
//Функция к
онфигурирования




//Конфигурирование режимов работы ЦАП


DAC_InitStructure.DAC_Trigger = DAC_Trigger;
//Источник запуска


DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
//Встроенный генераторś не используется


DA
C_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0xA00;
//Маска/амплитуда для встроенного генератора


DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
//Разреш
.
выходного буфера повышенной мощности


DAC_Init(DAC_Channel_1, &DAC_InitS
tructure);
//Функция конфигурирования для DAC1

#ifdef USE_DAC2


DAC_Init(DAC_Channel_2, &DAC_InitStructure);
//Функция конфигурирования для DAC2

#endif



//Общее разрешение работы ЦАПř загрузка начального значения
данных ЦАП (код
-

смещенный)


DAC_Cmd(DAC_Channel_1, ENABLE);



#ifdef USE_DAC2


DAC_Cmd(DAC_Channel_2, ENABLE);



#endif


}


//
--------------------------------
-------------------------------------------

// РАЗРЕШЕНИЕ/ЗАПРЕТ ГЛОБАЛЬНЫХ ПРЕРЫВАНИЙ ОТ ТАЙМЕРА

void DACTimerInterruptConfig(FunctionalState NewState)

{


NVIC_InitTypeDef NVIC_InitStructure;
//Структура конфигурации прерываний



NV
IC_InitStructure.NVIC_IRQChannel = TIMD_IRQn;
//Номер (линия) прерывания


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//Приоритет группы


NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//Приоритет внутри группы


NVIC_I
nitStructure.NVIC_IRQChannelCmd = NewState;
//Разрешение/запрет прерывания


NVIC_Init(&NVIC_InitStructure);
//Функция конфигурирования

}


//
---------------------------------------------------------------------------

/* Ш
А Б Л О Н

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ ТАЙМЕРА

// Вызывается с заданной частотой дискретизации ЦАПŜ

// Код для передачи в ЦАП
-

смещенныйř выравненный влевоŜ

uint16_t DACData1ř DACData2Ś //Данные для ЦАП в смещенном коде

void
TIMD_IRQHandler(void)

{


if (TIM_GetITStatus(TIMDř TIM_IT_Update) != RESET) //Проверка флага типа прерывания


{ //(необязательнаř если других типов нет)


TIM_ClearITPendingBit(TIMD, TIM_IT
_Update)Ś //Очистка флага


DAC_SetChannel1Data(DAC_Align_12b_Lř DACData1)Ś //Загрузка данных в ЦАП 1


DAC_SetChannel2Data(DAC_Align_12b_Lř DACData2)Ś //Загрузка данных в ЦАП 2


}

}

*/

//
-----------------------------------
----------------------------------------



Заголовочный

модуль
dac.h

/**


******************************************************************************


* Файл dacŜh


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ1


* Описаниеś Функции инициали
зации и обслуживания ЦАП


******************************************************************************


*/


#ifndef _DAC_H

#define _DAC_H


/* В следующих определениях вместо TIM7 могут быть использованы TIM2ř TIM4ř TIM5ř TIM7 */

#define TIMD

TIM7

#define DAC_Trigger_TD_TRGO DAC_Trigger_T7_TRGO

#define RCC_APB1Periph_TIMD RCC_APB1Periph_TIM7

#define TIMD_IRQn TIM7_IRQn

#define TIMD_IRQHandler TIM7_IRQHandler


/* Определения при использовании TIM6ś

#define TIMD

TIM6

#define DAC_Trigger_TD_TRGO DAC_Trigger_T6_TRGO

#define RCC_APB1Periph_TIMD RCC_APB1Periph_TIM6

#define TIMD_IRQn TIM6_DAC_IRQn

#define TIMD_IRQHandler TIM6_DAC_IRQHandler

*/


/* Объявления функций для их использова
ния в других программных модулях */

void DACInit(uint32_t SamplingFreq);

void DACTimerInterruptConfig(FunctionalState NewState);


//
---------------------------------------------------------------------------

#endif
/* _DAC_H */



Исходный модуль
codec.c

/*
*


******************************************************************************


* Файл codecŜc


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ0


* Описаниеś Функции инициализации и обслуживания аудиокодека


**********************************
********************************************


*/


#include "stm32_p407.h"
//Файл конфигурации отладочной платы STM32
-
P407

#include "codec.h"
//Функции для работы с кодеком


//
------------------------------------------
---------------------------------

// ИНИЦИАЛИЗАЦИЯ ЗВУКОВОГО КОДЕКА

/*


Формат данных для аудиокодека
-

16
-
разрядный дополнительный кодř


с учетом включенного после аудиокодека усилителяś


код 0111 1111 1111 1111 соответствует Uвых = +UmŚ


ко
д 0000 0000 0000 0000 соответствует Uвых = 0Ś


код 1000 0000 0000 0000 соответствует Uвых =
-
Um;


где Um примерно равно 1 В



Рекомендуемые настройки PLL I2S для I2S_Mode_Master


Частота PLLI2SN PLLI2SR I2SDIV


8000 Гц 256 5 1
2


16000 Гц 213 2 13


22050 Гц 429 4 9


32000 Гц 213 2 6


44100 Гц 271 2 6


48000 Гц 258 3 3


Реальная частота дискретизацииś 1 МГц * PLLI2SN / PLLI2SR / I2SDIV / 512


PLLI2
SN PLLI2SR
-

задаются в RCC_PLLI2SConfig(PLLI2SNř PLLI2SR)


I2SDIV вычисляется в библиотечной I2S_Init()



Для задания частоты дискретизации в stm32f4xx_spiŜh объявлены следующие константы


#define I2S_AudioFreq_192k ((uint32_t)192000)


#define I2S_AudioFreq_96k ((uint32_t)96000)


#define I2S_AudioFreq_48k ((uint32_t)48000)


#define I2S_AudioFreq_44k ((uint32_t)44100)


#define I2S_AudioFreq_32k ((uint32_t)32000)



#define I2S_AudioFreq_22k ((uint32_t)22050)


#define I2S_AudioFreq_16k ((uint32_t)16000)


#define I2S_AudioFreq_11k ((uint32_t)11025)


#define I2S_AudioFreq_8k ((uint32_t)8000)

*/

void
SoundCodecConfig(uint32_t AudioFreq)

{


//Структуры конфигурации


GPIO_InitTypeDef GPIO_InitStructure;


I2S_InitTypeDef I2S_InitStructure;



//Конфигурирование синтезатора ФАПЧ для интерфейса I2S (PLL I2S)


RCC_PLLI2SConfig(213,2);


//Разрешение рабо
ты PLL I2S


RCC_PLLI2SCmd(ENABLE);


//Ожидание готовности PLL I2S


while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY));


//Задание PLL I2S как источника тактирования I2S


RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);


//Разрешение тактирования модуля

SPI3/I2S3 по шине APB1


RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);


//Деинициализация (сброс) интерфейса SPI3/I2S3


SPI_I2S_DeInit(SPI3);



//Конфигурирование интерфейса I2S3


I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
//Реж
имś _SlaveTx _SlaveRx _MasterTx _MasterRx


I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
//Стандартś _Phillips _MSB _LSB _PCMShort _PCMLong


I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
//Форматś _16b _16bextended _24b _32b


I2
S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
//Разрешение выдачи на выход тактового сигнала


I2S_InitStructure.I2S_AudioFreq = AudioFreq;
//Частота дискретизацииś _8k ŜŜŜ _192k


I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;

//Исходный уровень тактового сигналаś _Low _High


I2S_Init(SPI3, &I2S_InitStructure);
//Функция конфигурирования



//Запрет прерывания I2S3 TXE


SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, DISABLE);




//Конфигурирование выводов

процессора


//Разрешение тактирования портов Ař Bř C


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);



//Конфигурирование PA15 (внешний сигнал I2S3_WS)


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;


GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;


GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


GPIO_Init(GPIOA, &GPIO_InitStructure);


GPIO_PinAFConfig
(GPIOA, GPIO_PinSource15, GPIO_AF_SPI3);
//Подключение вывода к I2S



//Конфигурирование PB3 (внешний сигнал I2S3_CK) и PB5 (внешний сигнал I2S3_SD)


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;


GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;


GPIO_InitStructure.GPIO_Mode = GPIO_Mod
e_AF;


GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


GPIO_Init(GPIOB, &GPIO_InitStructure);


GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);


GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_
AF_SPI3);



//Конфигурирование PC7 (внешний сигнал I2S3_MCK)


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;


GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;


GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;


GPIO_InitStr
ucture.GPIO_Speed = GPIO_Speed_50MHz;


GPIO_Init(GPIOC, &GPIO_InitStructure);


GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_SPI3);



//Разрешение определенного типа прерыванийś при пустом передающем буфере


SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, EN
ABLE);



//Разрешение глобальных прерываний


SoundCodecInterruptConfig(ENABLE);



//Разрешение работы интерфейса SPI3/I2S3


I2S_Cmd(SPI3, ENABLE);

}


//
---------------------------------------------------------------------------

// РАЗРЕШЕНИЕ/ЗАПРЕТ
ГЛОБАЛЬНЫХ ПРЕРЫВАНИЙ ОТ SPI3/I2S3 (КОДЕКА)

void SoundCodecInterruptConfig(FunctionalState NewState)

{


NVIC_InitTypeDef NVIC_InitStructure;
//Структура конфигурации прерываний



NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;

//Номер (линия) прерывания


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
//Приоритет группы


NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//Приоритет внутри группы


NVIC_InitStructure.NVIC_IRQChannelCmd = NewState;
//Разрешение/запрет прерывания


NVIC_Init(&NVIC_InitStructure);
//Функция конфигурирования

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ I2S3 (КОДЕКА)

// Вызывается

с двойной частотой дискретизацииŜ

// За одно обслуживание передается 16
-
битный отсчет одного каналаŜ

// Вызов вторичного обработчика Sample_Handler()ř формирующего отсчеты

// сразу двух каналовř происходит в 2 раза режеŜ

// Формат данных для кодека
-

доп
олнительныйŜ


int16_t DataChannel1, DataChannel2;
//Выходные отсчеты

uint16_t select_chan = 0;
//Флаг переключателя каналов


void SPI3_IRQHandler(void)

{


//Прове
рка флага запроса


{


SPI_I2S_ClearFlag(SPI3, SPI_I2S_FLAG_TXE);
//Сброс флага запроса прерывания


if (!select_chan)


{


Sample_Handler();
//Вторичный обработчик


SPI_I2S_SendData(SPI3, DataChannel1);
//Переда
ча кодеку отсчета первого канала


}


else SPI_I2S_SendData(SPI3, DataChannel2);
//Передача кодеку отсчета второго канала


select_chan ^= 1;
//Переключение каналов


}

}

//
---------------------------------------------------
------------------------



Заголовочный

модуль
codec.h

/**


******************************************************************************


* Файл codecŜh


* Copyright (C) 2015 МГТУ МИРЭА


* Версия 2Ŝ0


* Описаниеś Функции инициализации и обслуживания аудиокодека


******************************************************************************


*/


#ifndef _CODEC_H

#define _CODEC_H


/* Объявления функций для их использования в других программных модуля
х */

void SoundCodecConfig(uint32_t AudioFreq);

void SoundCodecInterruptConfig(FunctionalState NewState);

void Sample_Handler(void);
//Эта функция
-

для реализации в другом модуле


#endif

/* _CODEC_H */



1
.

Изме3ения 4 21м1щью ана01г
1
-
9и731в1г1 23е1б3аз1ва5
е



Исходный

модуль

D:
\
ARM
\
Work
\
Lab
3
_
adc
\
main.c

//
---------------------------------------------------------------------------

//

// УЧЕБНЫЙ ПРОЕКТ

// Измерения с помощью аналого
-
цифрового преобразователя

// Copyright (C) 2015 М
ГТУ МИРЭА

//

// Для тестирования работы АЦП используется установленный на плате потенциометр

// (триммер)ř посредством которого на разряде порта PC0 можно изменять напряжение

// в пределах 0ŜŜŜ3Ŝ3 ВŜ Разряд PC0 имеет альтернативные функцииś аналоговые в
ходы

// ADC1_IN10, ADC2_IN10, ADC3_IN10.

// Проект иллюстрирует измерение медленно меняющихся уровней сигналаř слежение

// за выходом значений за заданные границыŜ

//

//
---------------------------------------------------------------------------


#includ
e "stm32_p407.h"
//Файл конфигурации отладочной платы STM32
-
P407

#include "adc.h"
//Функции для работы с АЦП

#include "lcd.h"
//Функции для работы с дисплеем


#define AV
ERAGE 200
//Число усреднений данных с АЦП


//
---------------------------------------------------------------------------

// ПОДПРОГРАММЫ ВРЕМЕННЫХ ЗАДЕРЖЕК

// Входной аргументś значение задержки в миллисекундах / микросекундахŜ

v
oid Delay_ms(int ms)

{


volatile int i;


while (ms
--
) { i = 28000; while (
--
i); }

}

void Delay_us(int us)

{


volatile int i;


while (us
--
) { i = 20; while (
--
i); }

}


//
---------------------------------------------------------------------------

// ГЛАВ
НАЯ ФУНКЦИЯ

int main()

{


long AdcData;
//Суммированные данные с АЦП


unsigned short UData16;
//Приведенный смещенный (беззнаковый) код


short Data16;
//П
риведенный дополнительный (знаковый) код


int Average = 1;
//Текущее число усреднений


int i;
//Текущая переменная цикла


NVIC_InitTypeDef NVIC_InitStructure;
//Стр
уктура конфигурации прерываний




//Инициализация кнопок


STM_PBInit(BUTTON_WAKEUP, BUTTON_MODE_GPIO);
//Кнопка WAKEUP выхода из программы


STM_PBInit(BUTTON_RIGHT, BUTTON_MODE_GPIO);
//Позиция джойстика для включения режима усреднения


STM
_PBInit(BUTTON_LEFT, BUTTON_MODE_GPIO);
//Позиция джойстика для выключения режима усреднения


STM_PBInit(BUTTON_DOWNř BUTTON_MODE_GPIO)Ś //Позиция джойстика для временной остановки измерений



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


STM_LEDInit(LED3)
; STM_LEDOff(LED3);




//Инициализация дисплея


LCD_Init(); LCD_Clear(1);


LCD_FontSize(11);


LCD_FontColor(0x0F0);


LCD_TextPos(1ř1)Ś LCD_print("ВЫРАВНИВŜВЛЕВО")Ś


LCD_TextPos(1ř4)Ś LCD_print("ВЫРАВНИВŜВПРАВО")Ś


LCD_FontColor(0x08F);


LCD_TextPo
s(1ř2)Ś LCD_print("СмещŜ ДополнŜ")Ś


LCD_TextPos(1ř5)Ś LCD_print("СмещŜ ДополнŜ")Ś


LCD_FontColor(0xFFF);



//Инициализация и первичный запуск АЦП


ADC_Initialize(ADC2, ADC_Channel_10, 0);


ADC_SoftwareStartConv(ADC2);



//Конфигурирование прерыван
ий от АЦП


NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
//Номер (линия) прерывания


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//Приоритет группы


NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

//Приоритет внутри группы


NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//Разрешение/запрет прерывания


NVIC_Init(&NVIC_InitStructure);
//Функция конфигурирования



//Программирование АЦП в режиме "а
налогового сторожа"


ADC_AnalogWatchdogSingleChannelConfig(ADC2, ADC_Channel_10);
//Выбор канала


ADC_AnalogWatchdogThresholdsConfig(ADC2, 3500, 500);
//Верхний и нижний пороги


ADC_ITConfig(ADC2, ADC_IT_AWD, ENABLE);

//Разрешение прерываний от "сторожа"


ADC_AnalogWatchdogCmd(ADC2, ADC_AnalogWatchdog_SingleRegEnable);
//Разрешение "аналогового сторожа"



//Цикл в основной программе


while (1)


{


//Включение/отключение режима усреднения


if (STM_PBGetS
tate(BUTTON_RIGHT))


{ Average = AVERAGE;


LCD_TextPos(1,0); LCD_print("
-

Усреднение
-
");


}


if (STM_PBGetState(BUTTON_LEFT))


{ Average = 1;


LCD_TextPos(1,0); LCD_print(" ");


}




//Пользовательская остановка

измерений для чтения показаний






//Цикл по измерениям


for (i = Average, AdcData = 0; i � 0; i
--
)


{


while (!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC));
//Ожидание окончания преобразования


AdcD
ata += ADC_GetConversionValue(ADC2);
//Ввод и суммирование показаний


ADC_SoftwareStartConv(ADC2);
//Новый запуск преобразования


Delay_ms(1);


}




//Преобразование кода с АЦП


UData16 = AdcData / Average;

//Вычисление среднего


Data16 = UData16 ^ 0x8000;
//Преобразование смещенного кода в дополнительный



//Вывод результатов на дисплей


LCD_TextPos(1,3); LCD_print("%5d", UData16);
//Смещенный с выравн
иванием влево


LCD_TextPos(8,3); LCD_print("%6d", Data16);
//Дополнительный с выравниванием влево


Data16� �= 4; UData16 ��= 4;
//Имитация выравнивания вправо


LCD_TextPos(1,6); LCD_print("%5d", UData16);
//Смещенны
й с выравниванием вправо


LCD_TextPos(8,6); LCD_print("%6d", Data16);
//Дополнительный с выравниванием вправо




if (Average AVERAGE) Delay_ms(300);
//Период обновления индикации


STM_LEDOff(LED3);

//Гашение индикатора "аналогового сторожа"




//Проверка нажатия кнопки WAKEUP завершения работы (сброса процессора)


if (STM_PBGetState(BUTTON_WAKEUP)) NVIC_SystemReset();


}

}


//
----------------------------------------------------------
-----------------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ АЦП

void ADC_IRQHandler(void)

{


if (ADC_GetFlagStatus(ADC2, ADC_FLAG_AWD) != RESET)
//Проверка флага "аналогового сторожа"


{


ADC_ClearFlag(ADC2, ADC_FLAG_AWD);
//Сброс флага


STM_LEDO
n(LED3);
//Сигнализация о выходе уровня за пределы


}

}


//
---------------------------------------------------------------------------



2
.

Выв1д 4игна01в 4 и4210ьз1ванием ЦАП и а6ди1#1де#а


Исходный

модуль

D:
\
ARM
\
Work
\
La
b
3
_
dac
\
main.c

//
---------------------------------------------------------------------------

//

// УЧЕБНЫЙ ПРОЕКТ

// Вывод сигналов с использованием ЦАП и аудиокодека

// Copyright (C) 2015 МГТУ МИРЭА

//

// Формат данных для ЦАП
-

12
-
разрядный смещенны
й кодś

// код 1111 1111 1111 соответствует Uвых = максимум (практически Vref)Ś

// код 1000 0000 0000 соответствует Uвых = Vref / 2Ś

// код 0000 0000 0000 соответствует Uвых = минимум (практически 0)Ś

// где Vref
-

опорное напряжение (для отла
дочной платы равно напряжению питания)

//

// Формат данных для аудиокодека
-

16
-
разрядный дополнительный кодř

// с учетом дополнительного усилителя после аудиокодекаś

// код 0111 1111 1111 1111 соответствует Uвых = +UmŚ

// код 0000 0000 0000 0000

соответствует Uвых = 0Ś

// код 1000 0000 0000 0000 соответствует Uвых =
-
Um;

// где Um примерно равно 1 В

//

//
---------------------------------------------------------------------------


#include "stm32_p407.h"
//Файл конфигурации о
тладочной платы STM32
-
P407

#include "dac.h"
//Константы и функции для работы с ЦАП

#include "codec.h"
//Функции для работы с кодеком


//#define DMA_ENA //Определение для варианта использов
ания DMA


uint16_t DACData1, DACData2;
//Данные для ЦАП в смещенном коде

extern int16_t DataChannel1,
//Данные для кодека в дополнительном коде


DataChannel2;
// (определены в модуле codecŜc)




//Таблицы отсчетов сигналов (в смещенном формате)

uint16_t Signal0[] = { 8000,11000,14000,17000,20000,23000,26000,29000,


32000,35000,38000,41000,44000,47000,50000,53000 };

uint16_t Signal1[] = { 12000,12000,
12000,12000,52000,52000,52000,52000,


12000,12000,12000,12000,52000,52000,52000,52000 };

uint16_t Signal2[] = { 22000,32000,42000,52000,52000,52000,52000,52000,


42000,32000,22000,12000,12000,12000,12000,12000 };


//

ОСЦИЛЛОГРАММЫ ТЕСТОВЫХ СИГНАЛОВ НА ВЫХОДЕ ЦАП






uint16_t* Signal = Signal0;
//Указатель на одну из таблиц отсчетов


uint16_t index_dac;
//Индекс отсчета сигналаř выводимого через ЦАП

uint16_t index_codec;

//Индекс отсчета сигналаř выводимого через кодек

int signal_type;
//Тип генерируемого сигнала (номерś 0ř 1 или 2)


void DMA_DAC_Initialize(void);

void DMA_CODEC_Initialize(void);


//
-----------------------------------------
----------------------------------

// ГЛАВНАЯ ФУНКЦИЯ

int main()

{


//Инициализация органов управления в режиме генерации запросов прерывания


STM_PBInit(BUTTON_WAKEUP, BUTTON_MODE_EXTI);
//Кнопка WAKEUP


STM_PBInit(BUTTON_RIGHT, BUTTON_MODE_EXTI);

//Позиции джойстика


STM_PBInit(BUTTON_LEFT, BUTTON_MODE_EXTI);


STM_PBInit(BUTTON_UP, BUTTON_MODE_EXTI);



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


STM_LEDInit(LED1); STM_LEDInit(LED2); STM_LEDInit(LED3); STM_LEDInit(LED4);



//Инициализация ЦАП


DACInit(16000
);
//Аргумент
-

частота дискретизации в Гц

#ifndef DMA_ENA


DACTimerInterruptConfig(ENABLE);
//Разрешение прерываний от таймера

#else
// (в режиме DMA
-

запрещено)


DM
A_DAC_Initialize();
//Если задан режим DMAř его инициализация

#endif




//Инициализация кодека


SoundCodecConfig(I2S_AudioFreq_11k);
//Аргумент
-

частота дискретизации в Гц


DMA
_CODEC_Initialize();
//Функция задания режима DMA для кодека



//Программная генерация запроса прерывания для выбора начального типа сигнала


EXTI_GenerateSWInterrupt(EXTI_Line11);




//Цикл в основной программе


while (1)


{



__WFI();
//Режим пониженного энергопотребления ("сон")


}

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ ТАЙМЕРА ТАКТИРОВАНИЯ ЦАП (в режиме DMA не использу
ется)

// Код для передачи в ЦАП
-

смещенныйř выравненный влевоŜ

#ifndef DMA_ENA

void TIMD_IRQHandler(void)

{


uint16_t DACData;


STM_LEDOn(LED4);
//Отладочная метка (вывод "1")


if (TIM_GetITStatus(TIMD, TIM_IT_Update)

!= RESET)
//Проверка источника прерывания


{


TIM_ClearITPendingBit(TIMD, TIM_IT_Update);
//Сброс флага запроса прерывания


switch (signal_type)
//Ветвление по типу сигнала


{ case 0: DACData = Signal0[index_d
ac++]; break;


case 1: DACData = Signal1[index_dac++]; break;


case 2: DACData = Signal2[index_dac++]; break;


}


index_dac &= 0xF;
//Инкремент индекса с возвратом в 0


DAC_SetChannel1Data(DAC_Align_12b_
L, DACData);
//Передача данных в ЦАП


}


STM_LEDOff(LED4);
//Отладочная метка (вывод "0")

}

#endif


//

ОСЦИЛЛОГРАММА ОТЛАДОЧНОГО СИГНАЛА
-
МЕТКИ



//
-------------------------------------------------------------------
--------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОДЕКА

// Выборка отсчета из текущей таблицыř преобразование в дополнительный кодř

// загрузка в оба каналаř инкремент индекса отсчета с переходом на началоŜ

void Sample_Handler(void)

{


DataChannel1 = DataChannel2 = S
ignal[index_codec++] ^ 0x8000;


index_codec &= 0xF;

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЙ ОТ ВНЕШНИХ ЛИНИЙ EXTI_Line5ŜŜŜEXTI_Line9

// В нашем случае это линия 6
-

разряд порта PG6 (джойст
ик "вправо")ř

// линия 7
-

разряд порта PG7 (джойстик "вверх")Ŝ

// Константа EXTI_LineX является маской для соответствующего разряда XŜ

void EXTI9_5_IRQHandler(void)

{


if (EXTI_GetITStatus(EXTI_Line6) != RESET)
//Проверка источника
прерывания (номера линии)


{


EXTI_ClearITPendingBit(EXTI_Line6);
//Сброс флага запроса прерывания


signal_type = 2;
//Установка номера нового типа сигнала


Signal = Signal2;
//Установк
а указателя на отсчеты нового сигнала


STM_LEDOn(LED3);
//Включение индикатора выбранного типа сигнала


STM_LEDOff(LED1); STM_LEDOff(LED2);
//Отключение других индикаторов


}



if (EXTI_GetITStatus(EXTI_Line7) !=
RESET)
//Проверка источника прерывания (номера линии)


{


EXTI_ClearITPendingBit(EXTI_Line7);
//Сброс флага запроса прерывания


signal_type = 1;
//Установка номера нового типа сигнала


Signal = Signal1;

//Установка указателя на отсчеты нового сигнала


STM_LEDOn(LED2);
//Включение индикатора выбранного типа сигнала


STM_LEDOff(LED1); STM_LEDOff(LED3);
//Отключение других индикаторов


}

}


//
---
------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЙ ОТ ВНЕШНИХ ЛИНИЙ EXTI_Line10ŜŜŜEXTI_Line15

// В нашем случае это линия 11
-

разряд порта PG11 (джойстик "влево")

void EXTI15_10_IRQHandler(void)

{


if (EXTI_
GetITStatus(EXTI_Line11) != RESET)
//Проверка источника прерывания (номера линии)


{


EXTI_ClearITPendingBit(EXTI_Line11);
//Сброс флага запроса прерывания


signal_type = 0;
//Установка номера нового типа сигнала


Signal = Signal0;
//Установка указателя на отсчеты нового сигнала


STM_LEDOn(LED1);
//Включение индикатора выбранного типа сигнал


STM_LEDOff(LED2); STM_LEDOff(LED3);
//Отключение други
х индикаторов


}

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ ВНЕШНЕЙ ЛИНИИ EXTI_Line0

// К данной линии
-

разряду порта PA0
-

подключена кнопка WAKEUP

void EXTI0_IRQHandler(void)

{


NVIC_Sy
//Сброс процессора
-

завершение программы

}


//
---------------------------------------------------------------------------

// ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПРЯМОГО ДОСТУПА К ПАМЯТИ (DMA) ДЛЯ ЦАП

// Обслуживание ЦАП осуществляе
т контроллер DMA1 с каналами
-
потокамиś

// DMA1_Stream5 (для DAC1)ř

// DMA1_Stream6 (для DAC2)Ŝ

// Для старта передачи данных необходим запрос по каналу
-
запросу с номером DMA_Channel_7Ŝ

// Для прямой загрузки данных в DAC1 можно использовать регистры (с
мŜ stm32f4xxŜh)ś

// DHR12R1
-

12
-
битный код с выравниванием влево

// DHR12L1
-

12
-
битный код с выравниванием вправо

// DHR8R1
-

8
-
битный код с выравниванием влево

//

void DMA_DAC_Initialize(void)

{


DMA_InitTypeDef DMA_InitStructure;

//Структура конфигурации канала DMA



RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
//Разрешение тактирования контроллера DMA


DMA_DeInit(DMA1_Stream5);
//Начальная устано
вка (сброс) канала


DMA_InitStructure.DMA_Channel = DMA_Channel_7;
//Номер источника запроса для канала


DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC
-
�DHR12L1;
//Адрес перифер
.
устройства (регистра ЦАП)


DMA_InitStructur
e.DMA_Memory0BaseAddr = (uint32_t)&Signal2;
//Адрес буфера памяти (отсчетов сигнала)


DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
//Направл
.

передачиś память
-
> периферия


DMA_InitStructure.DMA_BufferSize = sizeof(Signal2)

/ 2;
//Число транзакций для передачи буфера


DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//Автоувеличение адреса периферииś нет


DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//Автоувеличение адр
еса памятиś да


DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
//Размер транзакции для памятиś


//

полуслово


DMA_InitStructure.DMA_MemoryDataSize =

DMA_PeripheralDataSize_HalfWord;
//Размер транзакции для периферииś


//

полуслово


DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//Режим передачи буфер
аś циклический


DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//Уровень приоритетаś высокий


DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
//Использование промежуточного FIFOś нет


DMA_InitStructure.DMA_FIFOTh
reshold = DMA_FIFOThreshold_HalfFull;
//Порог для FIFO (здесь не используется)


DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//Размер пакета для памятиś одиночный


DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Singl
e;
//Размер пакета для периферииś одиночный


DMA_Init(DMA1_Stream5, &DMA_InitStructure);
//Функция конфигурирования



DMA_Cmd(DMA1_Stream5, ENABLE);
//Разрешение работы канала DMA



DAC_DMACmd
(DAC_Channel_1, ENABLE);
//Разрешение запроса на DMA от ЦАП 1

}


//
---------------------------------------------------------------------------

// ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПРЯМОГО ДОСТУПА К ПАМЯТИ ДЛЯ КОДЕКА

// Обслуживание инте
рфейса SPI3/I2S3ř используемого для связи с кодекомř

// осуществляет контроллер DMA1 с каналами
-
потоками DMA1_Stream5ř DMA1_Stream7

// и каналом
-
запросом DMA_Channel_0 (запрос формируется при пустом буфере передачи)Ŝ

// Регистр для загрузки данных
-

SPI3
-

DR.

// Функция разрешения запросаś SPI_I2S_DMACmd(SPI3ř SPI_I2S_DMAReq_Txř ENABLE)Ś

// Необходимо также обеспечитьś

//
-

запрет прерываний с частотой дискретизацииŚ

//
-

отдельные коды для каждого канала кодекаŚ

//
-

коды в дополнительном формате (со

знаком)Ŝ

void DMA_CODEC_Initialize(void)

{

}


//
---------------------------------------------------------------------------



3
.

Ди4#3е5иза9ия 4игна01в 4 21м1щью АЦП


Исходный

модуль

D:
\
ARM
\
Work
\
Lab
3
_
discret
\
main.c

//
--------------------------------------
-------------------------------------

//

// УЧЕБНЫЙ ПРОЕКТ

// Дискретизация сигналов

// Copyright (C) 2015 МГТУ МИРЭА

//

// В проекте демонстрируютсяś

// генерация тестового гармонического сигналаŚ

// оцифровка этого сигнала посредством АЦПŚ

//

вывод сигнала через ЦАП аудиокодекаŜ

// Физическая связь выхода генератора и входа АЦП осуществлена

// благодаря двойной альтернативной функции разряда порта PA4Ŝ

//

//
---------------------------------------------------------------------------


// Заг
оловочные файлы

#include "stm32_p407.h"
//Файл конфигурации отладочной платы STM32
-
P407

#include "arm_math.h"
//Определения и функции библиотеки CMSIS DSP Library

#include "adc.h"
//Функции для работ
ы с АЦП

#include "dac.h"
//Константы и функции для работы с ЦАП

#include "codec.h"
//Функции для работы с кодеком


//
---------------------------------------------------------------------------

// ОБЪЯВЛЕНИЯ ДАННЫ
Х

int16_t DataADC1, DataADC2;
//Текущие отсчеты сигнала с АЦП

extern int16_t DataChannel1,
//Данные для кодека в дополнительном коде


DataChannel2;
// (определены в модуле codecŜc)

TIM_TimeBaseInitTypeDef Tim
eBase;
//Структура конфигурации базового таймера

NVIC_InitTypeDef NVICstruct;
//Структура конфигурации прерываний


//
---------------------------------------------------------------------------

// ГЛАВНАЯ ФУНКЦИЯ

int main()

{


//Счетчик д
ля реализации периода изменения тестовой индикации


volatile uint32_t i = 0;



//Задание 4
-
х уровней групповых приоритетов и 4
-
х уровней приоритетов в каждой группе


NVIC_PriorityGroupConfig(NVIC_
PriorityGroup
_2);




//Инициализация тестовых индикатор
ов


STM_LEDInit(LED1); STM_LEDInit(LED2); STM_LEDInit(LED3); STM_LEDInit(LED4);



//Инициализация кнопок


STM_PBInit(BUTTON_TAMPER, BUTTON_MODE_GPIO);


STM_PBInit(BUTTON_WAKEUP, BUTTON_MODE_GPIO);



//Инициализация ЦАП
-

как генератора входного сигна
ла для АЦП


DACInit(192000);


DACTimerInterruptConfig(ENABLE);



//Инициализация генератора частоты дискретизации АЦПŚ для этой цели


// задействован таймер 8 с собственной частотой тактирования 168 МГц


RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENA
BLE);


TimeBase.TIM_Period = 1680000u/44100
-
1;


TimeBase.TIM_Prescaler = 100
-
1;


TimeBase.TIM_ClockDivision = 0;


TimeBase.TIM_CounterMode = TIM_CounterMode_Up;


TIM_TimeBaseInit(TIM8, &TimeBase);


TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update)
;


TIM_Cmd(TIM8, ENABLE);



//Инициализация двухканального АЦП с запуском от события перезагрузки таймера 8


ADC_Initialize(ADC1, ADC_Channel_4, ADC_ExternalTrigConv_T8_TRGO);


ADC_Initialize(ADC2, ADC_Channel_4, ADC_ExternalTrigConv_T8_TRGO);



//Кон
фигурирование прерываний от АЦП (по событию окончания преобразования)


ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);


NVICstruct.NVIC_IRQChannel = ADC_IRQn;


NVICstruct.NVIC_IRQChannelPreemptionPriority = 2;


NVICstruct.NVIC_IRQChannelSubPriority = 0;


NVIC
struct.NVIC_IRQChannelCmd = ENABLE;


NVIC_Init(&NVICstruct);



//Инициализация кодека как устройства вывода сигнала


SoundCodecConfig(I2S_AudioFreq_192k);



//Основной цикл


while (1)


{


if (i++ == 0x800) STM_LEDOff(LED1);
//Тестовое упр
авление индикатором


if (i == 0xB0000) STM_LEDOn(LED1), i = 0;



if (STM_PBGetState(BUTTON_WAKEUP)) NVIC_SystemReset();
//Проверка на завершение


}

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВ
АНИЯ ОТ ТАЙМЕРА ТАКТИРОВАНИЯ ЦАП

void TIMD_IRQHandler(void)

{


static int16_t arg_sin;


STM_LEDOn(LED2);


TIM_ClearITPendingBit(TIMD, TIM_IT_Update);




arg_sin = (arg_sin + 0x200) &

0x7FFF;


STM_LEDOff(LED2);

}


//
---------------------------------------------------------------------------

// ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ АЦП

void ADC_IRQHandler(void)

{


STM_LEDOn(LED4);


ADC_ClearFlag(ADC1, ADC_FLAG_EOC);


Value(ADC1);


DataChannel1 = DataADC1 ^ 0x8000;




DataChannel2 = DataADC2 ^ 0x8000;


STM_LEDOff(LED4);

}


//
---------------------------------------------------------------------------

// ОБСЛУЖИВАНИЕ ПРЕРЫВАНИЯ
ОТ КОДЕКА

// Вызывается из обработчика прерывания ŜŜŜ_IRQHandler()ř реализованного в codecŜc

void Sample_Handler(void)

{


//Выводимые значения
-

в DataChannel1ř DataChannel2

}


//
---------------------------------------------------------------------------




Приложенные файлы

  • pdf 24023279
    Размер файла: 283 kB Загрузок: 0

Добавить комментарий