Jump to content

    

alexsandr-ter

Участник
  • Content Count

    95
  • Joined

  • Last visited

Community Reputation

0 Обычный

About alexsandr-ter

  • Rank
    Частый гость

Контакты

  • Сайт
    Array
  • ICQ
    Array
  1. Не поделишься готовым проектом?
  2. Добрый день Уважаемые форумчане! Кто может мне помощь в решении проблемы: есть макетки ATmega16A и enc28j60 в соответствии с данной темой http://we.easyelectronics.ru/electro-and-p...s-enc28j60.html написал прошивку, но как всегда ничего не работает :crying: Уже весь мозг сломал. Вроде все сделал как указано на сайте, но что-то не стреляет. Проект прикладываю. Кто сможет, помогите ENC28j60_v1.1.7z
  3. Поставил компаратор и все стало ОК. Огромное всем спасибо!
  4. Здравствуйте! Уважаемые форумчане! Кто может посоветовать электрическую схему формирования 10-100 пс видеоимпульсов?
  5. В общем, сначала я пустил импульс с датчика Холла через разделительный конденсатор и подтягивающий резистор на FT порт МК. Однако, этот вариант не подошел, так как возникали ложные срабатывания. Поэтому я остановился на компараторе.
  6. Датчик нужен для подсчета частоты вращения двигателя. Модель SS495
  7. Здравствуйте уважаемые форумчане! Кто может посоветовать, как подружить датчик Холла и STM. Датчик подключен к ноге PB6 вот код: int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 1){ NVIC_DisableIRQ(TIM4_IRQn); State = 0; while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, tt); NVIC_EnableIRQ(TIM4_IRQn); } for(i = 0; i < 50000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgLED, gpio_cfgHOLE; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgLED); GPIO_StructInit(&gpio_cfgHOLE); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); gpio_cfgHOLE.GPIO_Pin = GPIO_Pin_6; gpio_cfgHOLE.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &gpio_cfgHOLE); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base2; TIM_TimeBaseStructInit(&timer_base2); timer_base2.TIM_Prescaler = 72 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base2.TIM_Period = 10; TIM_TimeBaseInit(TIM3, &timer_base2); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic2; timer_ic2.TIM_Channel = TIM_Channel_1; timer_ic2.TIM_ICPolarity = TIM_ICPolarity_Rising; timer_ic2.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic2.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic2.TIM_ICFilter = 100; TIM_PWMIConfig(TIM2, &timer_ic2); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM4, TIM_TS_TI1F_ED) ; /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM4, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM4_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM4_IRQHandler(){ uint8_t sample1, sample2; if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_CC1); GPIOA->ODR ^= GPIO_Pin_1; do { sample1 = ReadHole(); sample2 = ReadHole(); } while (sample1!=sample2); if(state == 0){ GPIOA->ODR ^= GPIO_Pin_1; tt = 1; state = 1; } else{ tt = 0; } } } uint8_t ReadHole(){ return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6); }
  8. добавил проверку ошибки исчезли convert.INT = pos; while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1] & convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1] | convert.CHAR[0]);
  9. Огромное всем спасибо!!! Ну сбоить будет в любом случае, это не ПЛИС. Я думаю отправлять данные сразу на UART, а фильтровать на ПК. Только не совсем пока понятно как отфильтровывать. При вращении периодически сбоит, но я думаю с МК уже ничего не выжмешь. Кстати код: #include "main.h" ////////////////////////////////////////////////////////////////////// int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 1){ NVIC_DisableIRQ(TIM3_IRQn); State = 0; //pos = //pos_1; if(pos != old_pos){ convert.INT = pos; while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); old_pos = pos; } NVIC_EnableIRQ(TIM3_IRQn); } for(i = 0; i < 100000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgA, gpio_cfgB, gpio_cfgLED; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgA); GPIO_StructInit(&gpio_cfgB); GPIO_StructInit(&gpio_cfgLED); gpio_cfgA.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgA.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10 | GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_6; gpio_cfgA.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio_cfgA); gpio_cfgB.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgB.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14| GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11; gpio_cfgB.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio_cfgB); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base; TIM_TimeBaseStructInit(&timer_base); timer_base.TIM_Prescaler = 72 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base.TIM_Period = 10; TIM_TimeBaseInit(TIM3, &timer_base); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic; timer_ic.TIM_Channel = TIM_Channel_1; timer_ic.TIM_ICPolarity = TIM_ICPolarity_Rising; timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic.TIM_ICFilter = 20; TIM_PWMIConfig(TIM3, &timer_ic); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM3, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM3_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM3_IRQHandler(){ uint16_t enc1, enc2; if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); do { enc1 = ReadEncoder(); enc2 = ReadEncoder(); } while (enc1!=enc2); // здесь используем правильное значение enc1. if(State == 0){ State = 1; pos = enc1; } GPIOA->ODR ^= GPIO_Pin_1; } } uint16_t ReadEncoder() { uint16_t PA, PB; PA = ~GPIOA->IDR; PB = ~GPIOB->IDR; return 0 | (PA & 0b0000000000100000) >> (6 - 0) | (PA & 0b0000010000000000) >> (11 - 1) | (PA & 0b0000001000000000) >> (10 - 2) | (PA & 0b0000000100000000) >> (9 - 3) | (PA & 0b0000000010000000) >> (8 - 4) | (PB & 0b1000000000000000) >> (15 - 5) | (PB & 0b0100000000000000) >> (14 - 6) | (PB & 0b0010000000000000) >> (13 - 7) | (PB & 0b0001000000000000) >> (12 - 8) | (PB & 0b0000100000000000) >> (11 - 9); }
  10. И сбоит, каждые 2-3 периода
  11. сделал так, но теперь не пойму почему данные с UART бьются #include "main.h" ////////////////////////////////////////////////////////////////////// int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 2){ NVIC_DisableIRQ(TIM3_IRQn); State = 0; pos = pos_1; if(pos != old_pos){ if(convert.INT >= 7168 || convert.INT <= -7160) { convert.INT = 0; while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); } else{ if((old_pos - pos) > 0){ convert.INT = convert.INT - pos; } else{ convert.INT = convert.INT + pos; } while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); } old_pos = pos; } NVIC_EnableIRQ(TIM3_IRQn); } for(i = 0; i < 100000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgA, gpio_cfgB, gpio_cfgLED; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgA); GPIO_StructInit(&gpio_cfgB); GPIO_StructInit(&gpio_cfgLED); gpio_cfgA.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgA.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10 | GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_6; gpio_cfgA.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio_cfgA); gpio_cfgB.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgB.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14| GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11; gpio_cfgB.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio_cfgB); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base; TIM_TimeBaseStructInit(&timer_base); timer_base.TIM_Prescaler = 72 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base.TIM_Period = 10; TIM_TimeBaseInit(TIM3, &timer_base); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic; timer_ic.TIM_Channel = TIM_Channel_1; timer_ic.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //TIM_ICPolarity_Rising; timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic.TIM_ICFilter = 2; TIM_PWMIConfig(TIM3, &timer_ic); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM3, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM3_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM3_IRQHandler(){ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /* Даём знать, что обработали прерывание */ if(State == 0){ State = 1; PA = GPIOA->IDR; PB = GPIOB->IDR; D0 = (~PA & 0b0000000000100000) >> 6; D1 = (~PA & 0b0000010000000000) >> 11; D2 = (~PA & 0b0000001000000000) >> 10; D3 = (~PA & 0b0000000100000000) >> 9; D4 = (~PA & 0b0000000010000000) >> 8; D5 = (~PB & 0b1000000000000000) >> 15; D6 = (~PB & 0b0100000000000000) >> 14; D7 = (~PB & 0b0010000000000000) >> 13; D8 = (~PB & 0b0001000000000000) >> 12; D9 = (~PB & 0b0000100000000000) >> 11; pos_1 = D0 | (D1 << 1) | (D2 << 2) | (D3 << 3) | (D4 << 4) | (D5 << 5) | (D6 << 6) | (D7 << 7) | (D8 << 8) | (D9 << 9); } else if(State == 1){ PA2 = GPIOA->IDR; PB2 = GPIOB->IDR; D0 = (~PA2 & 0b0000000000100000) >> 6; D1 = (~PA2 & 0b0000010000000000) >> 11; D2 = (~PA2 & 0b0000001000000000) >> 10; D3 = (~PA2 & 0b0000000100000000) >> 9; D4 = (~PA2 & 0b0000000010000000) >> 8; D5 = (~PB2 & 0b1000000000000000) >> 15; D6 = (~PB2 & 0b0100000000000000) >> 14; D7 = (~PB2 & 0b0010000000000000) >> 13; D8 = (~PB2 & 0b0001000000000000) >> 12; D9 = (~PB2 & 0b0000100000000000) >> 11; pos_2 = D0 | (D1 << 1) | (D2 << 2) | (D3 << 3) | (D4 << 4) | (D5 << 5) | (D6 << 6) | (D7 << 7) | (D8 << 8) | (D9 << 9); if(pos_2 == pos_1){ State = 2; } else{ State = 0; } } GPIOA->ODR ^= GPIO_Pin_1; } }
  12. Это я сделал #include "main.h" ////////////////////////////////////////////////////////////////////// int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 1){ NVIC_DisableIRQ(TIM3_IRQn); State = 0; PA = GPIOA_IDR; PB = GPIOB_IDR; D0 = (PA & 0b0000000000100000) >> 6; D1 = (PA & 0b0000010000000000) >> 11; D2 = (PA & 0b0000001000000000) >> 10; D3 = (PA & 0b0000000100000000) >> 9; D4 = (PA & 0b0000000010000000) >> 8; D5 = (PB & 0b1000000000000000) >> 15; D6 = (PB & 0b0100000000000000) >> 14; D7 = (PB & 0b0010000000000000) >> 13; D8 = (PB & 0b0001000000000000) >> 12; D9 = (PB & 0b0000100000000000) >> 11; /* D0 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); D1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11); D2 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10); D3 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9); D4 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8); D5 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15); D6 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14); D7 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); D8 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12); D9 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); */ pos = D0 | (D1 << 1) | (D2 << 2) | (D3 << 3) | (D4 << 4) | (D5 << 5) | (D6 << 6) | (D7 << 7) | (D8 << 8); if(pos <= convert.INT){ while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); pos = convert.INT; } NVIC_EnableIRQ(TIM3_IRQn); } for(i = 0; i < 100000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgA, gpio_cfgB, gpio_cfgLED; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgA); GPIO_StructInit(&gpio_cfgB); GPIO_StructInit(&gpio_cfgLED); gpio_cfgA.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgA.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10 | GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_6; gpio_cfgA.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio_cfgA); gpio_cfgB.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgB.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14| GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11; gpio_cfgB.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio_cfgB); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base; TIM_TimeBaseStructInit(&timer_base); timer_base.TIM_Prescaler = 720 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base.TIM_Period = 1; TIM_TimeBaseInit(TIM3, &timer_base); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic; timer_ic.TIM_Channel = TIM_Channel_1; timer_ic.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //TIM_ICPolarity_Rising; timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic.TIM_ICFilter = 2; TIM_PWMIConfig(TIM3, &timer_ic); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM3, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM3_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM3_IRQHandler(){ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /* Даём знать, что обработали прерывание */ State = 1; GPIOA->ODR ^= GPIO_Pin_1; } }
  13. Здравствуйте уважаемые форумчане! Хотел спросить у вас совета. Есть абсолютный энкодер с 1024 отсчетами угла поворота и stm32 работающий на 72 МГц, данные с энкодера передаются на МК через 10 выводов. Вал энкодера соединен с валом двигателя через шестерню с передаточным числом 1/7. Была написана программа для определения угла поворота и передачи его на ПК через UART. Тут возникло две проблемы: 1. Данные на ПК иногда передаются не корректно; 2. Как преобразовать угол поворота энкодера в угол поворота двигателя. вот код: #include "main.h" ////////////////////////////////////////////////////////////////////// int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 1){ NVIC_DisableIRQ(TIM3_IRQn); State = 0; D0 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); D1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11); D2 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10); D3 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9); D4 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8); D5 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15); D6 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14); D7 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); D8 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12); D9 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); pos = D0 | (D1 << 1) | (D2 << 2) | (D3 << 3) | (D4 << 4) | (D5 << 5) | (D6 << 6) | (D7 << 7) | (D8 << 8) | (D9 << 9); if(pos <= convert.INT){ while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); pos = convert.INT; } NVIC_EnableIRQ(TIM3_IRQn); } for(i = 0; i < 100000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgA, gpio_cfgB, gpio_cfgLED; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgA); GPIO_StructInit(&gpio_cfgB); GPIO_StructInit(&gpio_cfgLED); gpio_cfgA.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgA.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10 | GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_6; gpio_cfgA.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio_cfgA); gpio_cfgB.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgB.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14| GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11; gpio_cfgB.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio_cfgB); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base; TIM_TimeBaseStructInit(&timer_base); timer_base.TIM_Prescaler = 720 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base.TIM_Period = 1; TIM_TimeBaseInit(TIM3, &timer_base); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic; timer_ic.TIM_Channel = TIM_Channel_1; timer_ic.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //TIM_ICPolarity_Rising; timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic.TIM_ICFilter = 2; TIM_PWMIConfig(TIM3, &timer_ic); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM3, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM3_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM3_IRQHandler(){ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /* Даём знать, что обработали прерывание */ State = 1; GPIOA->ODR ^= GPIO_Pin_1; } } Заранее спасибо!!!