MasterElectric

Members
  • Публикации

    92
  • Зарегистрирован

  • Посещение

Репутация

6 Обычный

О MasterElectric

  • Звание
    Осваивающийся

Электроника

  • Стаж в электронике
    6-10 лет
  1. STM32F10x SPI

    @Skyluck Настрой ногу как General PushPull Output.
  2. STM32 для чайника

    А где в Кубе написано что он генерирует пример "Эхо", он генерирует скелет VCP, а что вы там будете куда передавать и что принимать это ваше дело. И в реальном приложении такое и нафиг не нужно. @jgda87 Скорее всего тут проблемы Ардуино не обсуждают.
  3. STM32 для чайника

    @Darth_Vader А вы знаете основные принципы ООП, где они в HAL? Или по вашему указатель на структуру это и есть объект? И на этом ваше ООП и заканчиваеться.
  4. STM32 для чайника

    @ruhi Ну хорошо ОС это слишком жирно, пусть это будет менеджер задач. Но создавая велосипед я много чего узнаю о работе ядра. Я никуда не спешу т.к. это просто хобби, а работа с МК и программированием не связана совсем.
  5. STM32 для чайника

    @Koret Да я начинал с АВР + асм. Потом С начал и да только для того чтобы писать в регистры. Стандартные библиотеки я не использую т.к. опыта на С нет под ПК (только Delphi, VB). Но при программирования МК суть в том что вы понимаете зачем и куда вы что пишите, а как иначе? Если бы HAL был настолько хорош (написан на асм или качественно на С), да я бы и не вникал в те регистры. Пока вы делаете стандартные вещи, которые охватывает HAL, все будет просто шикарно, но напишите прием по модбасу например на скорости 2 мегабита/с. Просто суть в том что HAL ничего не дает, он не даст вам хорошую готовую библиотеку, а просто доступ к регистрам на абстрактном уровне, а зачем это нужно. Все и так настраиваеться без проблем в несколько строк кода, а имея опыт и наработки и свои библиотеки все просто и быстро. А знания ядра совсем уникальны, мало кто вообще понимает что там происходит, причем ядро у всех производителей одно и тоже. Асм знать тоже очень нужно, компилятор использует 75% из набора команд как я заметил самые простые. А вот тратить время на изучение HAL я не хочу. @mail_robot Тот крутой проект открыт? очень хотелось бы на него взглянуть. И никто не говорит что вы чего-то не понимаете если используете HAL. Просто мне например хочеться быть ближе к железу и понимать как устроен МК, нет ничего плохого в эффективности, она лежит на поверхности, регистры это и есть механизм для взаимодействия программы с микроконтроллером они для этого и созданы. А на счет дефайнов я имел в виду макросы, описывать имена регистров и биты словами понятными для человека это хорошо, я не призывал кодить используя цифры. (хотя я видел в сети пример где под примером программирования на CMSIS был лютый пи...ц, где кроме цифр ничего и небыло)
  6. STM32 для чайника

    @ttt222 Я 3 недели назад начал изучать асм, хватило 2 дней, хорошей книги и опыта работы с АВР + асм. Если что помогу. Пишу ОС. (пытаюсь).
  7. STM32 для чайника

    Особенно если учесть что излишние дефайны это большое зло. Да что там спорить просто люди не хотят вникать и разбираться, взяли пример работает и хорошо, а что там с оптимизацией и качеством не важно. Вот пример: const Typ_Port OutPins[] = {PB12, PB13, PB14, PB15, PA8, PA9, PA10, PA11, NC}; void Sys_ClockInit(void) {// HSE = 8000000; SYSCLK = 72000000; APB1 = 36000000; APB2 = 72000000 FLASH->ACR = 0x30 | FLASH_ACR_LATENCY_2; // RCC->CR |= RCC_CR_HSEON; //включаем генератор HSE while(!(RCC->CR & RCC_CR_HSERDY)); //ожидание готовности HSE RCC->CFGR = RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9 | RCC_CFGR_PPRE1_2; //источник тактовых сигналов для PLL выбираем HSE RCC->CR |= RCC_CR_PLLON; //включаем PLL while(!(RCC->CR & RCC_CR_PLLRDY)); //ожидание готовности PLL RCC->CFGR |= RCC_CFGR_SW_PLL; //выбираем PLL для тактирования // включаем тактирование модулей RCC->AHBENR = 0x00000014 | RCC_AHBENR_DMA1EN; RCC->APB1ENR = RCC_APB1ENR_TIM4EN | RCC_APB1ENR_USART2EN | RCC_APB1ENR_USBEN; RCC->APB2ENR = RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_TIM1EN; GPIO_SetModeList((gpOutput_GeneralPushPull | gp50MHz), OutPins); } Все просто и понятно, и совсем не асм)
  8. STM32 для чайника

    Ну вот например раздутый код: void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) { uint32_t position; uint32_t ioposition = 0x00; uint32_t iocurrent = 0x00; uint32_t temp = 0x00; uint32_t config = 0x00; __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ uint32_t registeroffset = 0; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */ /* Check the parameters */ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); /* Configure the port pins */ for (position = 0; position < GPIO_NUMBER; position++) { /* Get the IO position */ ioposition = ((uint32_t)0x01) << position; /* Get the current IO position */ iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition; if (iocurrent == ioposition) { /* Check the Alternate function parameters */ assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); /* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */ switch (GPIO_Init->Mode) { /* If we are configuring the pin in OUTPUT push-pull mode */ case GPIO_MODE_OUTPUT_PP: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP; break; /* If we are configuring the pin in OUTPUT open-drain mode */ case GPIO_MODE_OUTPUT_OD: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD; break; /* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */ case GPIO_MODE_AF_PP: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP; break; /* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */ case GPIO_MODE_AF_OD: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD; break; /* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */ case GPIO_MODE_INPUT: case GPIO_MODE_IT_RISING: case GPIO_MODE_IT_FALLING: case GPIO_MODE_IT_RISING_FALLING: case GPIO_MODE_EVT_RISING: case GPIO_MODE_EVT_FALLING: case GPIO_MODE_EVT_RISING_FALLING: /* Check the GPIO pull parameter */ assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); if(GPIO_Init->Pull == GPIO_NOPULL) { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING; } else if(GPIO_Init->Pull == GPIO_PULLUP) { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; /* Set the corresponding ODR bit */ GPIOx->BSRR = ioposition; } else /* GPIO_PULLDOWN */ { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; /* Reset the corresponding ODR bit */ GPIOx->BRR = ioposition; } break; /* If we are configuring the pin in INPUT analog mode */ case GPIO_MODE_ANALOG: config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG; break; /* Parameters are checked with assert_param */ default: break; } /* Check if the current bit belongs to first half or last half of the pin count number in order to address CRH or CRL register*/ configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2) : ((position - 8) << 2); /* Apply the new configuration of the pin to the register */ MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset ), (config << registeroffset)); /*--------------------- EXTI Mode Configuration ------------------------*/ /* Configure the External Interrupt or event for the current IO */ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) { /* Enable AFIO Clock */ __HAL_RCC_AFIO_CLK_ENABLE(); temp = AFIO->EXTICR[position >> 2]; CLEAR_BIT(temp, ((uint32_t)0x0F) << (4 * (position & 0x03))); SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03))); AFIO->EXTICR[position >> 2] = temp; /* Configure the interrupt mask */ if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) { SET_BIT(EXTI->IMR, iocurrent); } else { CLEAR_BIT(EXTI->IMR, iocurrent); } /* Configure the event mask */ if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) { SET_BIT(EXTI->EMR, iocurrent); } else { CLEAR_BIT(EXTI->EMR, iocurrent); } /* Enable or disable the rising trigger */ if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) { SET_BIT(EXTI->RTSR, iocurrent); } else { CLEAR_BIT(EXTI->RTSR, iocurrent); } /* Enable or disable the falling trigger */ if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) { SET_BIT(EXTI->FTSR, iocurrent); } else { CLEAR_BIT(EXTI->FTSR, iocurrent); } } } } } /** * @brief Handles DMA interrupt request. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval None */ void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) { /* Transfer Error Interrupt management ***************************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET) { /* Disable the transfer error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE); /* Clear the transfer error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if (hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /* Half Transfer Complete Interrupt management ******************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET) { /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) { /* Disable the half transfer interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); } /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF; if(hdma->XferHalfCpltCallback != NULL) { /* Half transfer callback */ hdma->XferHalfCpltCallback(hdma); } } } /* Transfer Complete Interrupt management ***********************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET) { if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) { /* Disable the transfer complete interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC); } /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_NONE); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferCpltCallback != NULL) { /* Transfer complete callback */ hdma->XferCpltCallback(hdma); } } } } И это только то что на поверхности. Зачем эти излишества? Зачем куда-то тратить время и флеш? Причем над каждым модулем (DMA, USART и т.д.) стоят структуры данных для всех этих ваших пустых абстракций которые жрут СОЗУ. Я тоже пишу библиотеки и хочу комфортно программировать, но для хранения например ножки порта у меня тратиться 1 байт, и этот 1 байт описывает на каком порту какая нога привязана. И тоже есть функции для настройки портов, например по списку, но код короче раза в 4 чем в HAL. И мануал на HAL под 2000 страниц, а изучив CMSIS и другие МК будет проще изучать и использовать, CMSIS для всех МК один.
  9. STM32 для чайника

    @Koret ООП это уж точно не HAL. Я писал на С++ пробовал, вот там реально создавать библиотеки ориентированные на работу с объектами, указал нужный USART при инициализации класса и все, нужно хоть все 8 используй однотипно, очень удобно. Библиотека сама настроит пины нужного USART, настроит работу прерываний и сама будет их обрабатывать, а для взаимодействия с основной программой создал глобальную переменную Event в которой устанавливаються нужные флаги. И для запуска всего этого нужно закинуть папку с библиотекой, и создать экземпляр класса. Вот к такому кодингу стремлюсь я. И там нет никакой лишней абстрактности все на CMSIS, теперь думаю некоторые вещи на асм переписать. Сейчас правда все забросил понял что нужно ОС еще осваивать. А "ужас" в том что одну строку при работе с регистрами в HAL используют целые функции, ну вот например: GPIO_SetBits(GPIOA, GPIO_Pin_4); и что разве нет в этом ничего ужасного? Я уже не говорю про работу с флагами, а прерывания это просто жесть.
  10. STM32 для чайника

    Путь HAL такой же тупиковый как и Arduino, есть черта через которую не перейти и чтобы написать нечто большее чем предлагает вам HAL, нужно все-равно опускаться до уровней регистров или даже до уровня ассемблера и читать мануалы. Как можно програмировать МК и не знать как там что устроено? Я вот читаю и фигею с того как вы хвалите тут HAL, обычно люди которые понимают уровень регистров и смотрят в HAL видят там кошмар и ужас, где вы там нашли что-то хорошее? И как по мне работа с HAL мало чем на самом деле отличаеться от работы с регистрами на CMSIS, потому как он вообще не дает никаких преимуществ вы все-равно все настраиваете руками. И меня особо улыбнуло сравнение программировать на регистрах с опусканием до уровня ассемблера, да это точно такой же С/С++. Тем более что страдать нужно только 1 раз когда пишешь первый раз, потом опыт и код накапливаеться и все дальше все легко и просто.
  11. STM32 для чайника

    Я тут давал пример там АЦП + ПДП на CMSIS без всей этой ереси.
  12. STM32 для чайника

    У вас не будет чувства комфорта когда будете на асм писать т.к. 90% всех операций это пересылка между РОН и СОЗУ то интересного тут мало, я без проблем пишу на асме и на С, но асм это крайний случай (такие как ядро ОС). .align 3 .globl __Task_ContextSwitch .type __Task_ContextSwitch, %function __Task_ContextSwitch: ldr r0, =0xE000ED00 ldr r1, [r0, #4] orr r1, 0x10000000 str r1, [r0, #4] bx lr Да и есть диззасм и в отладчике его видно прям там где останов кода был, все есть, если что работать не будет всегда ошибку можно выловить отладчиком. Для того чтобы кодить везде и всегда купите себе нетбук)
  13. STM32 для чайника

    @Zhuk72 Да можно просто в стартап дописать мигалку, он же на асме)) но это ппц)))
  14. STM32 для чайника

    @ttt222 Кортексы это вам не AVR. У STM есть множество шин, которые работают на разных тактовых частотах, и наскольо я слышал компилятор сам оптимизирует последовательность выполнения программы - на какую шину когда что пихать, а может это ядро делает само. Но асм очень многообразный и сложный. Если хотите все контролировать пишите на С + CMSIS. Без SPL HAL. Так вы будете чувствовать периферию МК и если очень нужно делать вставки на асм или писать целые функции. Попробуйте их просто освоить на С, посмотрите что выйдет) а потом на асм. Или просто написать мигающий светодиод.
  15. STM32 для чайника

    @Koret Ищи в спецификации.