Миландр

Ключевым подразделением нашей компании
является Центр Проектирования интегральных микросхем
Текущее время: 2021-мар-01 09:28

Часовой пояс: UTC+03:00




Начать новую тему  Ответить на тему  [ 4 сообщения ] 
Автор Сообщение
 Заголовок сообщения: Помощь начинающему =)
СообщениеДобавлено: 2018-окт-19 19:24 
Не в сети

Зарегистрирован: 2018-окт-18 22:29
Сообщения: 8
Организация: ФГУП "ВНИИА"
Здравствуйте, по долгу службы хорошо было бы овладеть работой с АЦП, увидеть как что работает, что выдает и т.д. На работе имеется отладочная плата LDM-K1986BE92QI, на мк написано MDR32F9Q2I ARM 1523 (возможно это важно). Нашёл в различных пособиях и лабниках по программированию Миландра и этого типа мк примеры программ. Первая - ввод бита информации в com-port и получение его обратно (я сделал увеличенный на единицу для наглядности) работает на ура. Вторая - работа с АЦП, а именно снятие напряжения с определённого вывода. Хотел разобраться как и что - создал проект в Keil, объединил эти две программы, ожидая, что через com-port увижу символы, по котором можно расшифровать напряжение на выводе (в проге PD7). :)

В результате получаю, что есть оцифровка сигнала, но...частично. от 0,03 до 0,1 В, 0,24 - 0,31, 0,44 - 0,52, 0,65 - 0,72, 0,85 - 0,93, 1,06 - 1,13, 1,27 - 1,33, 1,47 - 1,53, 1,67 - 1,73, 1,88 - 1,96, 2,09 - 2,16, 2,29 - 2,37, 2,51 - 2,57, 2,73 - 2,79, 2,92 - 3,00, 3,12 - 3,20.
При этом, в каждом из этих промежутков действительно меняются символы с % через цифры, заглавные и строчные буквы до }. Если перебирать по 10 мВ, то перед каждой такой областью, в 2-3-х значениях программа не выдаёт результат оцифровки. (длинные пробелы, перескок строки или просто ничего), также иногда сбивается выполнение программы и стирается весь терминал com-port (использую PuTTy). Ну а теперь основное - в остальных значениях программа выдаёт символ, напоминающий закрашенный прямоугольник.
Если у кого-нибудь было что-нибудь похожее или есть идеи в чём проблема (всё таки хочется оцифровывать диапазон от 0 до 3,3В), прошу помочь :roll: . Не судите строго программу,которую прикрепляю, её стиль и т.д., не профессиональный программист :D . Буду благодарен за помощь. :)
#include "MDR32F9Qx_port.h" 
#include "MDR32F9Qx_rst_clk.h"
#include "MDR32F9Qx_adc.h"
#include "stdbool.h"
#include "MDR32F9Qx_uart.h"
#include "MDR32Fx.h"

#define delay(T) for(i = T; i > 0; i--)
#define  SCALE 1
//#define SCALE 1252.5

 int i; //Счетчик для задержки циклом
 ADC_InitTypeDef ADC; //Общая инициализацинная структура подсистемы АЦП
 ADCx_InitTypeDef ADC1; //Инициализацинная структура для АЦП1
 
PORT_InitTypeDef PortInit;    // определение переменной для инициализации портов ввода вывода  
UART_InitTypeDef UART_InitStructure; // определение переменной для инициализации UART  
  
uint32_t uart2_IT_TX_flag = RESET;  // Флаг устанавливается после передачи одного байта  
uint32_t uart2_IT_RX_flag = RESET;  // Флаг устанавливается после приема одного байта


 void ADCInit()   { 
//Подача тактования на процессор и АЦП
 RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK | RST_CLK_PCLK_ADC, ENABLE);
 ADC_StructInit(&ADC); //Заполнение структуры умолч. значениями
 ADC_Init(&ADC); //Инициализация
 ADCx_StructInit(&ADC1);
 ADC1.ADC_ChannelNumber = ADC_CH_ADC7; //Switch to TRIM!!! //Выбор седьмого канала
ADC1.ADC_LevelControl = ADC_LEVEL_CONTROL_Disable;
  /* ADC1.ADC_LevelControl = ADC_LEVEL_CONTROL_Enable;
 ADC1.ADC_LowLevel = 3;
   ADC1.ADC_HighLevel = 0;*/
ADC1.ADC_LowLevel = 0;
ADC1.ADC_HighLevel = 0; 
 ADC1.ADC_DelayGo = 7;
 ADC1.ADC_Prescaler = ADC_CLK_div_512;
 ADC1_Init(&ADC1);
 
//Int 
//Инициализация прерываний АЦП
NVIC_EnableIRQ(ADC_IRQn);
NVIC_SetPriority(ADC_IRQn, 0);
//Включение прерываний по окончанию преобразования
 ADC1_ITConfig(ADCx_IT_END_OF_CONVERSION, ENABLE);
 ADC1_Cmd(ENABLE); //Включение АЦП1
       }
			 
void UART2_IRQHandler(void)  
{  
if (UART_GetITStatusMasked(MDR_UART2, UART_IT_RX) == SET)  
         //проверка установки флага прерывания по окончании приема данных  
  {  
    UART_ClearITPendingBit(MDR_UART2, UART_IT_RX);//очистка флага прерывания  
    uart2_IT_RX_flag = SET;   //установка флага передача данных завершена  
  }  
if (UART_GetITStatusMasked(MDR_UART2, UART_IT_TX) == SET)    
         //проверка установки флага прерывания по окончании передачи данных  
  {  
    UART_ClearITPendingBit(MDR_UART2, UART_IT_TX);  //очистка флага прерывания  
    uart2_IT_TX_flag = SET;   //установка флага передача данных завершена  
  }  
}  
			 
bool conInProgress; //Флаг «в процессе преобразования» 
unsigned int rawResult; //Необработанный результат 
unsigned char channel; //Номер канала
float result; //Результат в вольтах

void ADC_IRQHandler() {	//Обработчик прерываний АЦП
//Проверка что причина прерывания соответствует концу преобразования
if(ADC_GetITStatus(ADC1_IT_END_OF_CONVERSION)) { 
rawResult = ADC1_GetResult();  //Получение результата
channel = (rawResult & 0x1F0000) >> 16; 	//Сохранение номера канала
rawResult &= 0x00FFF; //Удаление номера канала из результата
//Преобразование результата в вольты
result = (float)rawResult / (float)SCALE;
conInProgress = false; //Очистка флага «в процессе преобр-я»
NVIC_ClearPendingIRQ(ADC_IRQn); //Очистка флага прерывания
     }
  }

int main(void) {
	static uint8_t ReciveByte=0x00; //данные для приема
		ADCInit();
	RST_CLK_HSEconfig(RST_CLK_HSE_ON);
		// static uint8_t ReciveByte=0x00; //данные для приема  
    // Включение HSE осциллятора (внешнего кварцевого резонатора) для обеспечения стабильной  
    // частоты UART 
      
    if (RST_CLK_HSEstatus() == SUCCESS){      
        // Если HSE осциллятор включился и прошел текст  
        // Выбор HSE осциллятора в качестве источника тактовых импульсов для CPU_PLL   
        // и установка умножителя тактовой частоты CPU_PLL равного 8 = 7+1   
        RST_CLK_CPU_PLLconfig(RST_CLK_CPU_PLLsrcHSEdiv1, 7);  
        // Включение схемы PLL  
        RST_CLK_CPU_PLLcmd(ENABLE);  
        if (RST_CLK_HSEstatus() == SUCCESS){ //Если включение CPU_PLL прошло успешно  
            RST_CLK_CPUclkPrescaler(RST_CLK_CPUclkDIV2); // Установка CPU_C3_prescaler = 2  
            RST_CLK_CPU_PLLuse(ENABLE);   
            // Установка CPU_C2_SEL от CPU_PLL выхода вместо CPU_C1 такта  
            /* Выбор CPU_C3 такта на мультиплексоре тактовых импульсов микропроцессора (CPU  
            clock MUX) */  
            RST_CLK_CPUclkSelection(RST_CLK_CPUclkCPU_C3);  
        }  
        else while(1);// блок CPU_PLL не включился  
    }  
    else while(1); // кварцевый резонатор HSE не включился  
    RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTF, ENABLE);  //Разрешение тактирования порта F  
    // заполнение полей переменной   PortInit для обеспечения работы UART  
    PortInit.PORT_PULL_UP = PORT_PULL_UP_OFF;
		PortInit.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;  
    PortInit.PORT_PD_SHM = PORT_PD_SHM_OFF;  
    PortInit.PORT_PD = PORT_PD_DRIVER;  
    PortInit.PORT_GFEN = PORT_GFEN_OFF;  
    PortInit.PORT_FUNC =     PORT_FUNC_OVERRID;   
    PortInit.PORT_SPEED = PORT_SPEED_MAXFAST;  
    PortInit.PORT_MODE = PORT_MODE_DIGITAL;  
  
    // Конфигурация 1 ножки порта PORTD как выхода (UART2_TX)   
    PortInit.PORT_OE = PORT_OE_OUT;  
    PortInit.PORT_Pin = PORT_Pin_1;  
    PORT_Init(MDR_PORTD, &PortInit);  
  
    // Конфигурация 2 ножки порта PORTD как входа (UART2_RX)  
    PortInit.PORT_OE = PORT_OE_IN;  
    PortInit.PORT_Pin = PORT_Pin_2;  
    PORT_Init(MDR_PORTD, &PortInit);  
  
    //Разрешение тактирования UART2  
    RST_CLK_PCLKcmd(RST_CLK_PCLK_UART2, ENABLE);  
    // Инициализация делителя тактовой частоты для UART2  
    UART_BRGInit(MDR_UART2, UART_HCLKdiv1);  
    // Разрешение прерывания для UART2  
    NVIC_EnableIRQ(UART2_IRQn);  
    // Заполнение полей для переменной UART_InitStructure   
    UART_InitStructure.UART_BaudRate   = 9600;    //тактовая частота передачи данных  
    UART_InitStructure.UART_WordLength = UART_WordLength8b; //длина символов 8 бит  
    UART_InitStructure.UART_StopBits   = UART_StopBits1;    //1 стоп бит  
    UART_InitStructure.UART_Parity     = UART_Parity_No;    // нет контроля четности  
    UART_InitStructure.UART_FIFOMode   = UART_FIFO_OFF;     // выключение FIFO буфера  
    
		/* Аппаратный контроль за передачей и приемом */  
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE;         
  
    UART_Init (MDR_UART2, &UART_InitStructure);   //Инициализация UART2  
    UART_ITConfig (MDR_UART2, UART_IT_RX, ENABLE);//Разрешение прерывания по приему   
    UART_ITConfig (MDR_UART2, UART_IT_TX, ENABLE);//Разрешение прерывания по окончани передачи  
  
    UART_Cmd(MDR_UART2, ENABLE); //Разрешение работы UART2  
  
			while (1) { 
        while (uart2_IT_RX_flag != SET); //ждем пока не не установиться флаг по приему байта  
        uart2_IT_RX_flag = RESET;                           //очищаем флаг приема  
        ReciveByte = UART_ReceiveData (MDR_UART2);  //считываем принятый байт 
    
delay(0xFFFF);
if (!conInProgress) {    //Не выполняется ли преобразование?
ADC1_Start();    //Начать преобразование!
conInProgress = true;    //Преобразование выполняется
       }				
        UART_SendData (MDR_UART2, ++ReciveByte);
 UART_SendData (MDR_UART2, rawResult);
UART_SendData (MDR_UART2, result);               //отправляем принятый байт, увеличенный на единицу обратно  
        while (uart2_IT_TX_flag != SET);                     //ждем пока байт уйдет  
        uart2_IT_TX_flag = RESET;                            //очищаем флаг передачи  
    }
 }
 


Вернуться к началу
 Заголовок сообщения: Re: Помощь начинающему =)
СообщениеДобавлено: 2018-окт-22 09:05 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1540
Откуда: Тула
Покажите что у Вас выводится в PuTTY.
Расскажите что Вы ожидаете там увидеть? (при разных напряжениях)
Как Вы видите работу этого кода?
Цитата:
UART_SendData (MDR_UART2, rawResult);
UART_SendData (MDR_UART2, result);

_________________
сочувствующий…


Вернуться к началу
 Заголовок сообщения: Re: Помощь начинающему =)
СообщениеДобавлено: 2018-окт-22 09:13 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 473
Организация: Milandr
Откуда: ПКК "Миландр"
Я бы поменял логику основного цикла, сейчас происходит:
- Прием слова ReciveByte по UART
- Запуск АЦП
- Передача ++ReciveByte
- Передача rawResult и result - Что в этих переменных, предыдущие значения или АЦП успел их обновить?

АЦП для измерения необходимо 28 тактов, но и делитель частоты выставлен в 512.

АЦП и UART работают правильно, значения не пропадают. Вы убедитесь в этом если отладчиком проверите значения выдаваемые АЦП. Полагаю, что проблема в логике работы программы.


Вернуться к началу
 Заголовок сообщения: Re: Помощь начинающему =)
СообщениеДобавлено: 2018-ноя-27 16:48 
Не в сети

Зарегистрирован: 2018-окт-18 22:29
Сообщения: 8
Организация: ФГУП "ВНИИА"
Действительно проблема в логике программы.
Поставил инициализацию АЦП в другую прогу и все заработало :)
Спасибо за направление мысли :)


Вернуться к началу
Показать сообщения за:  Поле сортировки  
Начать новую тему  Ответить на тему  [ 4 сообщения ] 

Часовой пояс: UTC+03:00


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти: 

Создано на основе phpBB® Forum Software © phpBB Limited
Русская поддержка phpBB