Перейти к содержанию

pokk

Участник
  • Публикаций

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

  • Посещение

Репутация

0 Обычный

Информация о pokk

  • Звание
    Частый гость

Посетители профиля

1 635 просмотров профиля
  1. , это я умею (см первый пост там их нету).
  2. Ну так там везде в функции tickDelay, ставят цикл ожидания, и все остальные процессы останавливаются на это время. Что бы потом пихать в проект ещё и RTOS, когда надо снять данные с датчика температуры и выдать их в usart =) Прерывания от таймера, это отдельный процесс как в RTOS, только без сохранения контекста =( + это очень легко можно запустить на любом процессоре, разобравшись только в таймере и кинув в него 1 функцию.
  3. Моя первая реазилация 1-wire была на прерываниях от таймера и чисто на switch case, это было дикая спагетти кода, потом частично завернул в функции, но все равно не нравилось как получилось, последний раз написал на protothreads, уже как-то глаз радует, а теперь сижу и опять не доволен не охото к каждому проекту пихать protothreads, + оборачивать макросами PT_BEGIN,PT_END Как можно красиво написать похожее чисто на си ? Думаю в сторону переключения адреса, но как это сделать красиво ? на protothreads получилось такое: //PT_YIELD(pt); - выход из функции, + сохранение место выхода #define SetDelay_us(value) TCCR3B=0x01; TCNT3H=(0xFFFF-value*(CPU_CLK/1000000))>>8;\ TCNT3L=(0xFFFF-value*(CPU_CLK/1000000));\ PT_YIELD(pt);\ PT_THREAD(Wire_Reset_thread(struct pt *pt,unsigned char *ReturnValue)){ static unsigned short int Ack[2]; PT_BEGIN(pt); //--------------------------------------------- Ack[0]=0; Ack[1]=0; //--Переключаем линию на выход и записываем 0-- Switch_Out(); SetDelay_us(480); //--Переключаем линию на выход----------------- Switch_In(); //--------------------------------------------- SetDelay_us(80); //--------------------------------------------- Ack[0]=T1; //--------------------------------------------- SetDelay_us(250); //--------------------------------------------- Ack[1]=T1; //--------------------------------------------- if((Ack[0] == 0)&&(Ack[1] ==1)){ *ReturnValue=SENSOR_INIT_VALIDATION_SUCCESS; }else{ //------------------------------------------------------------------------------------------ //*ReturnValue=SENSOR_INIT_VALIDATION_FAIL; if((Ack[0]==1)&&(Ack[1]==1)){ *ReturnValue=TYPE_T_SHORT_CIRCUIT_1; }else{ *ReturnValue=TYPE_T_SHORT_CIRCUIT_0; } //------------------------------------------------------------------------------------------ } //--------------------------------------------- PT_END(pt); }
  4. Раньше, тоже делал счет миллисекунд из прерывания, но последнее время стал использовать такой способ http://we.easyelectronics.ru/Soft/samyy-pr...nyy-taymer.html Только максимальное значение миллисекунд, которое можно задать зависит от таймера. А для сильно большой задержки, использую RTC, настроил что бы счетчик работал по секундам и считываю его, также. (только это относиться для stm32f1x, для stm32f4x RTC совсем другая )
  5. Перенести checksum, в начало

    А раньше почему, он не ругался ? Ведь я же диапазон не трогал совсем, или он как-то изменился из за того что я изменил секцию .checksum ?
  6. Перенести checksum, в начало

    Считаю CRC от 0x08000100 до 0x0803FFFC, и checksum в конце ложиться. Linker: place at address mem:__ICFEDIT_region_ROM_end__-3 { readonly section .checksum }; Тут считается, все равно и сходится с программный расчетом. Теперь, хочу что бы рассчитанное значение checksum положилось по адресу 0x08000000 (это типа шапка для бутлодера) Меняю в ликере: place at address mem:__ICFEDIT_region_ROM_start__ { readonly section .checksum }; И получаю ошибку IAR, о том что диапазон рассчитываемой checksum не делиться на 4 :wacko: а раньше почему делилось ? Про какой диапазон он ругается ?
  7. arhiv6, благодарю, надо будет разобраться в хуках. kolobok0, Спасибо за CI, не знал что есть такое, какая самая простая?
  8. Версия ПО+ GIT

    Добрый день, на писал на C# скрипт который от текущее время преобразует строку, и записываем массивом в файл, а этот файл подцепляю к проекту, и из массива вывожу на дисплей. Потом по дате можно поискать в логах GIT и найти комитет(нужный исходник), но это как-то не очень, было бы круче если тэг текушей ветки сразу бы заносился в массив, ну или что нибудь из GIT что бы можно было быстро и легко найти исходник(версию), зашитой программы. Что можно в GIT использовать в качестве идентификатора? Хотел ТЭГ, но 1) не нашел как узнать тэг текущей ветки 2) его надо в ручную инкрементировать =(
  9. Stm32f103 Injected simultaneous mode

    Настроил ADC1, ADC2 в режиме Injected simultaneous mode, запускается по триггеру от таймера 4 1) Так вот в прерывании флаг JEOC от какого ADC проверять ? судя по даташиту они должны выставиться у обоих одновременно. 2) можно ли менять в процессе работы АЦП номера каналов в регисте JSQR ? (естественно после того как он завершит преобразование группы) (Каналов АЦП где-то 11, хочу настроить,4+4 инжекторных канала + переключать в прерывании от АЦП на другую группу 8ми каналов) CODE //================================================================================ ================== /* * @Описание: Описание функции. * @Параметр: * @Возврат: Нету */ void Adc1_init(void){ //---------------------------------------------------------------------------------------------- RCC->APB2ENR |= RCC_APB2Periph_GPIOC; GPIO_INIT_PIN(GPIOC,10,GPIO_MODE_OUTPUT2_PUSH_PULL); GPIO_INIT_PIN(GPIOC,11,GPIO_MODE_OUTPUT2_PUSH_PULL); //---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //ADC init //------------------------------------------------------------------------- RCC_ADCCLKConfig(RCC_PCLK2_Div4); //тактирование АЦП не больше 14Mhz 36/4=9Mhz //------------------------------------------------------------------------- RCC->APB2ENR |= RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB; GPIO_INIT_PIN(GPIOA,2,GPIO_MODE_INPUT_ANALOG); GPIO_INIT_PIN(GPIOA,1,GPIO_MODE_INPUT_ANALOG); GPIO_INIT_PIN(GPIOB,1,GPIO_MODE_INPUT_ANALOG); //-------------------------------------------------------------------------------- RCC->APB2ENR |= RCC_APB2Periph_GPIOC; GPIO_INIT_PIN(GPIOC,0,GPIO_MODE_INPUT_ANALOG); GPIO_INIT_PIN(GPIOC,1,GPIO_MODE_INPUT_ANALOG); GPIO_INIT_PIN(GPIOC,2,GPIO_MODE_INPUT_ANALOG); GPIO_INIT_PIN(GPIOC,3,GPIO_MODE_INPUT_ANALOG); //---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- ADC1->CR1|=ADC_CR1_SCAN|ADC_CR1_JEOCIE; //---------------------------------------------------------------------------------------------- ADC1->CR1|=(5<<ADC_CR1_DUALMOD_POS); //---------------------------------------------------------------------------------------------- // 000(0): Timer 1 TRGO event // 001(1): Timer 1 CC4 event // 010(2): Timer 2 TRGO event // 011(3): Timer 2 CC1 event // 100(4): Timer 3 CC4 event // 101(5): Timer 4 TRGO event // 110(6): EXTI line15/TIM8_CC4 event (TIM8_CC4 is available only in high-density and XLdensity devices) // 111(7): JSWSTART ADC1->CR2|= (5<<ADC_CR2_JEXTSEL_POS) // 101(5): Timer 4 TRGO event |ADC_CR2_JEXTTRIG*1; //---------------------------------------------------------------------------------------------- // These bits are written by software to define the total number of conversions in the regular // channel conversion sequence. // 0000: 1 conversion // 0001: 2 conversions //ADC1->SQR1|= (3<<ADC_SQR1_L_POS); //---------------------------------------------------------------------------------------------- ADC1->JSQR|=(ADC1_LEN_Inj<<ADC_JSQR_JL_POS); //---------------------------------------------------------------------------------------------- //---------------------------Настраиваем соответствие инжектным каналам------------------------- //---------------------------------------------------------------------------------------------- ADC1->JSQR|=(13<<ADC_JSQR_JSQ1_POS_CH_1); ADC1->JSQR|=(1<< ADC_JSQR_JSQ1_POS_CH_2); ADC1->JSQR|=(2<< ADC_JSQR_JSQ1_POS_CH_3); //ADC1->JSQR|=(4<<ADC_JSQR_JSQ1_POS_CH_4); //---------------------------------------------------------------------------------------------- NVIC_SetPriority(ADC1_2_IRQn,1); //---------------------------------------------------------------------------------------------- NVIC_EnableIRQ(ADC1_2_IRQn); //---------------------------------------------------------------------------------------------- ADC1->CR2|=ADC_CR2_ADON; //---------------------------------------------------------------------------------------------- delay_us(100); ADC1->CR2 |= ADC_CR2_CAL; while(ADC_GetResetCalibrationStatus(ADC1)); //---------------------------------------------------------------------------------------------- }
  10. Цитата(2) Оставить SPI, специфический алгоритм общения с LCD вынести в контроллер. "Тормозные" операции, вроде таймаутов для LCD, не будут выполняться в базовой системе. Благодарю, в следующий раз по думаю в этом направлении, но пока увы, уже плата готова. Цитата(непонятно, что за RTOS) Это не RTOS, а просто объектный такой код, для понятия алгоритма, вот поспешил и не исправил, правильнее было так написать КодSTACK_SetTask(lcd_set_8bit_mode(0),0,100);       STACK_SetTask(WriteLCDcommand,0,100);         STACK_SetTask(WriteLCDcommand(0x30),0,0);     STACK_SetTask(WriteLCDcommand(0x30),0,0);       STACK_SetTask(WriteLCDcommand(0x3C),0,0);       STACK_SetTask(lcd_cursor_mode(LCD_ENABLE,CURSOR_ENABLE,BLINK),0,0); STACK_SetTask(WriteLCDcommand(0x1),0,0); Это я хотел, забуферизировать порядок вызова функций. Цитатапримерно так Это то понятно, а дальше как уходить от while, которая появляется в третей вложенной функции? Особенно интересно без средств ОС(переключения контекста). Как по максимуму сгруппировать все while , что бы потом спихнул все на DMA и ждешь 1 флаг завершения инициализации/обновления LCD ?
  11. Цитата1. На каком-либо процессоре реализовать свой "расширитель", а более правильно - универсальный контроллер LCD LCD, дисплей примитивный hd44780, так что сильно жырно для него использовать отдельный МК, если я правильно понял. Цитата4.2. Выдача инф. по 4.1. производится из видео-RAM (образ экрана LCD в требуемом формате). 4.3. Изменение буфера RAM выполняется асинхронно из любой задачи, из которой требуется вывод на LCD. Все так и сделано. Цитата4.1. Выдача инф. через SPI интерфейс выполняется задачей с низким приоритетом, по таймеру + флаги обновления (нет смысла выдавать инф. на дисплей, если она уже там отображается). Таймер - 0.2 .... 0.5 с. Выдача идет "пакетом", без квитирования и задержек на максимальной скорости, соотв-но зацикл невозможнн. Блин а тут не чисто SPI,I2C, управляющие выводы RS,RW,E идут от процессора а через расширитель только данные, изначально было так проше, что бы на 1 символ не приходилось 3 байта гнать
  12. Добрый день, в одном из проектов, подключил LCD индикатор через расширитель порта по I2C, но код получился, как-то не очень надежный, в общем сейчас появилось по больше времени, и решил ещё раз все обдумать и сделать нормальный модуль LCD, который можно в любой проект пихать. Но пока только какая то каша в голове. В общем вот примерно как-то так было, во время всех while, переключался на другие процессы через ОС. Теперь меня интересует, как бы все это сделать без ОС,( для самообразования!!). ну и желательно, прозрачный код, но это уже не обязательно. CODE //================================================================================ void DisplayUpdate(unsigned char *buf){ unsigned char LcdCountChar; unsigned char GetCharTemp; for(LcdCountChar=0;LcdCountChar<40;LcdCountChar++){ if(LcdCountChar==0){ WriteLCDcommand(ADDRESS_FIRST_ROW); } if(LcdCountChar==20){ WriteLCDcommand(ADDRESS_SECOND_ROW); } GetCharTemp=UTF_conversion(buf[LcdCountChar]); WriteLCDdata(GetCharTemp); } } //================================================================================ void WriteLCDdata(unsigned char data){ SetRS; WriteLCD_Nibble(data); data=data<<4; WriteLCD_Nibble(data); } //================================================================================ void WriteLCD_Nibble(unsigned char data){ SetE; SetW; //------------------------ GlobalData_Lcd=data; Pcf8575_Send_data(GlobalData_Lcd,GlobalData_Led_key_lcd); //PortLCD=(PortLCD&0xFF0F)|(data&0xF0); while(Pcf8575_Send_ok==1){} //Передача завершилась //------------------------ ClrE; } Как вот это: Кодwhile(Pcf8575_Send_ok==1){} //Передача завершилась вынести в самый верх что бы можно было по опрашивать в main? Была идея все данные закинуть в стек, а потом, их выдавать. где все функции будут запускаться в том порядке как их и устанавливали, но тогда получается на каждый чих( SetE;) внутри WriteLCD_Nibble надо делать тоже функцию, и все это в большую очередь выстроиться, ну и тут так же стала проблема в том что разные параметры передается,и помимо установки в стек обработчиков, надо ещё и параметры устанавливать. Кодvoid Lcd_init(void){     Lcd_pin_init();     LCD_ON();     //----------------     RTOS_SetTask(lcd_set_8bit_mode(0),0,100);           RTOS_SetTask(WriteLCDcommand,0,100);              RTOS_SetTask(WriteLCDcommand(0x30),0,0);          RTOS_SetTask(WriteLCDcommand(0x30),0,0);           RTOS_SetTask(WriteLCDcommand(0x3C),0,0);           RTOS_SetTask(lcd_cursor_mode(LCD_ENABLE,CURSOR_ENABLE,BLINK),0,0);     RTOS_SetTask(WriteLCDcommand(0x1),0,0);            RTOS_SetTask(Start_UpadeDispaly,0,0);       return } Думал сделать на КА, жестко прописать какие функции за кем вызываються, но тут 1) теряется читабельность(хотя с этим я уже мерился, так 1 раз все это прописать и больше туда возвращаться не планирую). 2) когда следуют одинаковые функции друг за другом типа 2 раза вызов функции WriteLCDcommand с разным параметром. как тут быть даже не знаю, делал ещё пред настройку(как бы буфер на 2 функции вперед), установку функции Next, которая будет выполнятся после установленной, но тут получилось все запутано совсем. Подскажите в какую сторону двигаться?.
  13. Благодарю, примерно в это направление и смотрел, останавливало меня только что при таком варианте нельзя будет(или можно?) отлаживать программу в пошаговом режиме, подцепить отладочный файл из другого проекта. Со структурой проекта пока совсем беда, как все вместе проверить не совсем понятно. PS: компилятор IAR.
  14. bootloader

    Как подцепить отладочный файл из другого проекта? Что бы в режиме отладки по СИ можно по шагам походить и по смотреть как все вместе работает. И вообще можно получить, общую прошивку bootloader+application?
  15. Добрый день подскажите с алгоритмом, есть bootloader Ehternet на stm32, он прошивается программатором с зашитой от считывания, и дальше TFTP закидывается основное приложение(application). В случае если application перехватят, как защититься что бы его, не смогли загрузить через свой "поддельный bootloader", тупо программатором со смешением. Пока думаю добавить в шапку application, уникальный идентификатор, что бы туда не пытались закидывать всякий мусор, но этот идентификатор можно блокнотом посмотреть, да и основное приложение как бы открытое получается.