UAKIVSO 0 27 мая, 2021 Опубликовано 27 мая, 2021 · Жалоба Итак, причина, по которой я пытаюсь наваять что нить по I2C и не использовать библиотеки/встроенные регисты в том, что уж очень хочется понять как оно работает и научиться управлять на уровне "дергания ножек" + прога в которой я ковыряюсь - EmBitz 1.11 Есть дисплей 1602 на I2C доп плате и собственно стм32Ф407 платка дискавери. Просьба сильно не пинать, а возможно указать тупиковость моих мыслей или движений. На сейчас объявляю инициализациб порта В ножек 7и8 таким образом void SET_I2C(void) { ///-----------------------------------SETUP PORTB6/7-----------------------------------------------------// RCC->APB1ENR|=0x200000; ///APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE) RCC->AHB1ENR|=0x02; ///AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE) GPIOB->MODER =0x5000; //32 bit for 16 inputs for 16 input 0x40000000, for 15 input 0x10000000...for 1 input 0x01. Means 01 for ech two bits if input GPIOB->OTYPER |=0xC0; //16 bit for 16 inputs for 16 input. Means 0 OR 1 for ech bits if use OR not use internal resistor GPIOB->OSPEEDR |=0xF000; //32 bit for 16 inputs. Means 00 for LOW speed or 01 for MEDIUM or 10 for HIGH or 11 for VERY HIGH speed GPIOB->PUPDR |=0x5000; //32 bit for 16 inputs. Means 00 for no pulup/puldown resistor or 01 for pulup or 10 for puldown or 11 RESERVED GPIOB->BSRRL |=0xC0; } Потом собственно бит старт и пресылка адреса (0х27) с частотой 400 Кгерц при частоте камня 168Мгерц void lcd_adr (uint8_t LCD_ADR) { ///-----------------------------------SEND ADDRESS--------------------------------------------------------// int n; n=0; ADDR_OK=0; while(!(GPIOB->IDR&0x40)){n++;if(n>500){break;}} GPIOB->BSRRH|=0x80;/// 0V onto PB7 while(GPIOB->IDR&0x80){n++;} n=0; GPIOB->BSRRH|=0x40;/// 0V onto PB6 while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x40){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x20){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x10){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x08){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x04){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x02){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (LCD_ADR&0x1){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(n<((168000000/4000000)*7)){n++;} GPIOB->MODER=(GPIOB->MODER)&0xFFFF3FFF; GPIOB->PUPDR=(GPIOB->PUPDR)&0xFFFF3FFF; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++;} if (!(GPIOB->IDR&0x80)) { ADDR_OK=1; } n=0; while(!(GPIOB->IDR&0x80)){n++; if(n>500){break;}} GPIOB->MODER |=0x5000; GPIOB->PUPDR |=0x5000; } Далее использую команду указатель на инструкцию (0х78)+(0х00), где последня 1я строка void lcd_cmd (uint8_t cmd) { ///-----------------------------------SEND COMMAND--------------------------------------------------------// int n; n=0; DATA_OK=0; while(!(GPIOB->IDR&0x40)){n++;if(n>500){break;}} n=0; GPIOB->BSRRH|=0x40;/// 0V onto PB6 while(n<((168000000/4000000)*7)){n++;} if (cmd&0x80){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x40){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x20){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x10){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x08){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x04){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x02){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(!(GPIOB->IDR&0xFF3F)){n++;} while(n<((168000000/4000000)*7)){n++;} if (cmd&0x01){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } GPIOB->BSRRH|=0xC0;/// 0V onto PB6/PB7 n=0; while(n<((168000000/4000000)*7)){n++;} GPIOB->MODER=(GPIOB->MODER)&0xFFFF3FFF; GPIOB->PUPDR=(GPIOB->PUPDR)&0xFFFF3FFF; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++;} if (!(GPIOB->IDR&0x80)) { DATA_OK=1; } n=0; while(!(GPIOB->IDR&0x80)){n++; if(n>500){break;}} GPIOB->MODER |=0x5000; GPIOB->PUPDR |=0x5000; } И вроде акнолоджмент приходит, но засветить ченить на дисплее не выходит.. в Маине такой алгоритм lcd_adr (0x27); if (ADDR_OK==1){ lcd_cmd (0x78); } if (DATA_OK==1){ lcd_cmd (0x00); } if (DATA_OK==1){ lcd_data (0x01); } Понимаю, что многие скажут, что бред, но может это возможно заставить работать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 27 мая, 2021 Опубликовано 27 мая, 2021 · Жалоба Зачем реализовать софтово то, что есть аппаратно? Особенно на таком жирном МК! Он же у вас находится в итоге большую часть времени в блокирующем ожидании. Нехорошо это. Хотя бы реализуйте конечный автомат с поллингом или же (еще лучше) - на таймере с ногодрыгом по DMA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 1 27 мая, 2021 Опубликовано 27 мая, 2021 · Жалоба Софтварно все пишется и довольно легко, но только вот нужно уметь программировать, постарайтесь счесть за инструкцию к действию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UAKIVSO 0 27 мая, 2021 Опубликовано 27 мая, 2021 · Жалоба 1 час назад, Eddy_Em сказал: Зачем реализовать софтово то, что есть аппаратно? Особенно на таком жирном МК! Он же у вас находится в итоге большую часть времени в блокирующем ожидании. Нехорошо это. Хотя бы реализуйте конечный автомат с поллингом или же (еще лучше) - на таймере с ногодрыгом по DMA. I2C лишь шаг к пониманию как дергать ножками - цель профинет касаемо ожидания - оптимизация будет позже, сначала нужно, дабы заработало 1 час назад, rkit сказал: Софтварно все пишется и довольно легко, но только вот нужно уметь программировать, постарайтесь счесть за инструкцию к действию. Возможно весь код поможет (выложить?), но хотелось бы пинок в правильном направлении ;) где я не так что-то накрутил И да, программировать на стл в сименсе могу, но си как то тяжко заходит - многого не знаю. Стилистика написания конечно корявая и не оптимизированная, но как только начнёт фурычить, то потрачу пару неделек на «причесывание и оптимизацию» «школьного кода» Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 27 мая, 2021 Опубликовано 27 мая, 2021 · Жалоба 19 minutes ago, UAKIVSO said: но хотелось бы пинок в правильном направлении Edit -> Format document Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 28 мая, 2021 Опубликовано 28 мая, 2021 · Жалоба 2 hours ago, UAKIVSO said: while(n<((168000000/4000000)*7)){n++;} if (cmd&0x04){GPIOB->BSRRL|=0x80;}/// 3V onto PB7; GPIOB->BSRRL|=0x40;/// 3V onto PB6; while(n<(168000000/400000)){n++; } Во втором случае задержки никакой не будет. И да, напомню, что эта задержка не детерминирована! Молчу уж о том, что magick numbers — моветон. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 1 28 мая, 2021 Опубликовано 28 мая, 2021 · Жалоба Нет, не нужно тратить пару неделек на оптимизацию кода, который можно сразу правильно написать за день. Вот так код должен выглядеть. Замени определения все тела scl_* sda_* на обращения к регистрам, если хочется именно так. https://github.com/liyanboy74/soft-i2c/blob/main/i2c_sw.c Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 28 мая, 2021 Опубликовано 28 мая, 2021 · Жалоба Логический анализатор подключите и отлаживайте свой ногодрыг, поглядывая на диаграммы I2C-шины. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UAKIVSO 0 28 мая, 2021 Опубликовано 28 мая, 2021 · Жалоба Спасибо за комменты, буду "курить" указанное выше Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UAKIVSO 0 4 июня, 2021 Опубликовано 4 июня, 2021 · Жалоба Итак, благодаря "волшебным пендалям" в заданном направлении получил аппаратный I2C без прерываний, но по флагам... Инициализация тут RCC->AHB1ENR|=0x02; ///AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE) GPIOB->MODER |= (2<<12) | (2<<14); /// Alternate function mode for PB6/PB7 GPIOB->AFR[0] |= (4<<24) |(4<<28); ///I2C -AF4 RCC->APB1ENR = (RCC->APB1ENR)&0xFFDFFFFF; I2C1->CR1 = 0x00; I2C1->CR2 = 0x00; RCC->APB1ENR |=(1<<21); I2C1->CR2 |= 42; ///APB1 speed in Mhz I2C1->CCR = 50; ///42Mhz/(2*100 kHz) for normal mode, for fast mode need to activate I2C master mode selection I2C1->TRISE = 43;/// 1ms/(1/42MHz) + 1 I2C1->CR1 |= (1<<10); ///ACK I2C1->CR1 |= 0x01; ///PE: Peripheral enable Собственно функция передача данных тут.. void Write_I2C_cmd(uint8_t device_address, uint8_t data) { uint32_t temp; char data_u, data_l; uint8_t data_t[4]; data_u =(data&0xf0); data_l =((data<<4)&0xf0); data_t[0] = data_u|0x0c; //en=1, rs=0 data_t[1] = data_u|0x08; //en=0, rs=0 data_t[2] = data_l|0x0c; //en=1, rs=0 data_t[3] = data_l|0x08; //en=0, rs=0 I2C1->CR1 |= I2C_CR1_START; ///START I2C I2C_CR1_START while (!(I2C1->SR1 & I2C_SR1_SB)) ///start condition was send { temp++; } I2C1->DR = (device_address<<1); ///SEND ADDRESS to DATA register while (!(I2C1->SR1 & I2C_SR1_ADDR)) ///address in DATA { temp++; } temp=I2C1->SR2; /// clear flags I2C_SR1_ADDR by read SR1 and then SR2 - SR1 was read in While loop I2C1->DR = data_t[0]; ///SEND data to DATA register while (!(I2C1->SR1 & I2C_SR1_TXE)) ///transfer complete { temp++; } I2C1->DR = data_t[1]; ///SEND data to DATA register while (!(I2C1->SR1 & I2C_SR1_TXE)) ///transfer complete { temp++; } I2C1->DR = data_t[2]; ///SEND data to DATA register while (!(I2C1->SR1 & I2C_SR1_TXE)) ///transfer complete { temp++; } I2C1->DR = data_t[3]; ///SEND data to DATA register while (!(I2C1->SR1 & I2C_SR1_TXE)) ///transfer complete { temp++; } I2C1->CR1 |= I2C_CR1_STOP; ///START I2C I2C_CR1_STOP } И все бы хорошо, да только вот банальное затирание 16 на 02 дисплея + две надписи тянут времени уж ОЧЕНЬ много.. Собственно команда lcd_clear(); lcd_put_cur(0,0); lcd_send_string("I2C1->CR1"); D=I2C1->CR1 |=0x00; lcd_put_cur(1,0); lcdSendHEX(D,15); И ее время выполнения в режиме 400 кГц берется более 10 милисекунд Понимаю, что можно оптимизировать возможно в 2-4 раза код=меньше кратно будут отсылаться данные, но вот все одно это будут 2-3 милисекунды... А жто много. для контоллера, который ничего не делает и столько времени тратит на пересылку ТОЛЬКО.. Вот поэтому и хотелось ручной ногодрыг или что-то такое, когда время, между позитивными флагами SCL будет использоваться для проходов программы. Прерывания не сильно хотелось бы внедрять = нет веры в си компилятор, не понятно, все ли гладко в итоге будет.. Собственно требуется от ГУРУ еще какой нить пинок в нужном направлении.. Может дадите толчок !? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 0 4 июня, 2021 Опубликовано 4 июня, 2021 · Жалоба Quote Прерывания не сильно хотелось бы внедрять = нет веры в си компилятор Что за компилятор то у Вас такой страшный что Вы его боитесь? Уверен, что через пару лет разработки Вы перечитаете своё сообщение и так же, как я, улыбнётесь. Чтобы уйти от блокирующего кода Вам могут помочь аппаратные средства МК: прерывания, DMA; программные средства: операционная система, машина состояний (конечный автомат). Прерывания, пожалуй, самый простой из доступных способов. И ещё, совет. Избегайте "магических чисел" при работе с регистрами периферии МК. Используйте макроопределения битов из файла "stm32F407xx.h" для своего процессора. Например для строки I2C1->CR1 |= 0x01; ///PE: Peripheral enable I2C1->CR1 |= I2C_CR1_PE; ///PE: Peripheral enable Будет легче читать код и искать ошибки Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UAKIVSO 0 4 июня, 2021 Опубликовано 4 июня, 2021 · Жалоба Использую EmBitz 1.11, так как халявный... возможно Вы правы, буду улыбаться со своих постов. Про магические числа понял, учту... Ну а если прерывания, то как с ними быть? К примеру делаю старт - пишу на дисплей что-то, отправляю в регистр адрес, далее на свой код перехожу... появляется прерывание по получению адреса.. в разных обработчиках разные куски тулить? туплю я чего-то, не складывается картинка.. :( Сори, что значит конечный автомат? Не совсем понимаю что это? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 0 4 июня, 2021 Опубликовано 4 июня, 2021 · Жалоба Вектор прерывания у модуля I2C один, следовательно и функция-обработчик будет одна, на все возможные события. Для мастер-передатчика надо будет обрабатывать следующие события (* я с I2C на F4xx семействе не работал, могут кое-где соврать). Следовательно в основной программе инициировали передачу посредством старт-условия, занялись другими делами. Сгенерировалось прерывание, в обработчике анализируете флаги статусного SR1, SR2. SB флаг установлен - шлёте байт адреса и выходите из обработчика. На следующей итерации установленный флаг ADDR укажет на то, что пора передавать данные (потребуется статическая переменная-счётчик количества байт). Как всё передадите в обработчике сгенерируете состояние "стоп". Это в своей сути и есть конечный автомат. Не буду вдаваться в теорию множеств и графов, я её не знал и забыл. В общих словах. У автомата есть устойчивые состояния: формирование старт-условия, передача I2C адреса, передачи I2C байта... Грубо говоря, все выражения внутри циклов while() в Вашем коде: где программа чего-то ждёт. А ждёт она входные сигналы - те флаги регистра SR1 проверкой которых занят МК внутри циклов. Т.е. для состояния "передача I2C адреса" входной сигнал s = I2C1->SR1 & I2C_SR1_ADDR. Если !s, автомат продолжает находиться в этом состоянии, s - выполняется функция перехода F (передача первого байта) и автомат оказывается в состоянии "передача I2C байта". В случае использования прерываний автомат обслуживается аппаратными средствами МК. То же самое можно сделать и программно. Я делаю, обычно на операторе switch. Каждая метка - состояние автомата. И периодически вызываете полученную функцию где-нибудь, в main() например. void i2c_tx_fsm(void) { static int state = 0; //ЛУЧШЕ В ВИДЕ enum с "говорящими" именами // Idle state case 0: //-состояние if (data_to_transmit) //-проферка входного сигнала { //-функция перехода I2C1->CR1 |= I2C_CR1_START; ///START I2C I2C_CR1_START state = 1; } break; // Wait start condition case 1: //-состояние if (I2C1->SR1 & I2C_SR1_SB) //-проферка входного сигнала { //-функция перехода I2C1->DR = (device_address<<1); ///SEND ADDRESS to DATA register state = 2; } break; // Wait Address send case 2: ....... default: satte = 0; break; } Читаемости коду такие конструкции не прибавляют, но это плата за однопоточность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UAKIVSO 0 4 июня, 2021 Опубликовано 4 июня, 2021 (изменено) · Жалоба идея понятна, я по такой сути делаю ЕМ, как в S77 стандарте типа этого void EM_LED (int i,int EM_ORIG) { int D; ///-----------------------------------LOAD DATA----------------------------------------------------------// internal_EM=(EM_ORIG + (EM[i]&0xFFFFC000)); Temp_EM=(internal_EM>>16)&0x3FFF;///read present step number ///-----------------------------------UPDATE COMPLETE/STATUS----------------------------------------------// if (!((internal_EM&0x3FFF) == Temp_EM)) {internal_EM=(internal_EM&0x7FFFBFFF);/*NO BIR 14&31*/;} ///-----------------------------------SELECT JUMP CONDITION - STEP OR TRANSITION--------------------------// if (internal_EM&0x4000){goto TRANSITION;}goto STEP; ///-----------------------------------STEP SELECTOR------------------------------------------------------// STEP:Temp_EM=internal_EM&0x3FFF;///read requested step number if (Temp_EM==0){goto STEP_0;} if (Temp_EM==100){goto STEP_100;} if (Temp_EM==200){goto STEP_200;} if (Temp_EM==300){goto STEP_300;} if (Temp_EM==400){goto STEP_400;} goto STEP_0;/// IF WRONG STEP ORDERED ///-----------------------------------TRANSITION SELECTOR-------------------------------------------------// TRANSITION:Temp_EM=internal_EM&0x3FFF;///read requested step number if (Temp_EM==0){goto TRANS_0;} if (Temp_EM==100){goto TRANS_100;} if (Temp_EM==200){goto TRANS_200;} if (Temp_EM==300){goto TRANS_300;} if (Temp_EM==400){goto TRANS_400;} goto TRANS_0;/// IF WRONG STEP ORDERED ///-----------------------------------STEP 0-------------------------------------------------------------// STEP_0:GPIOD->ODR =0xF000; GPIOD->BSRRL =0xF000;internal_EM|=0x4000;goto STEP_UPDATE; ///-----------------------------------TRANSITION 0--------------------------------------------------------// TRANS_0: internal_EM|=0x80000000; internal_EM= internal_EM+100;goto END; ///-----------------------------------STEP 100-------------------------------------------------------------// STEP_100:GPIOD->BSRRH =0x1000; GPIOD->BSRRL =0x8000; T[0]|=0x40000000;///SWITCH ON TIMER T[0]=T[0]&0xFFFFC000;///SET TIMER TO "0" SETPOINT T[0]|=10;///SET TIMER TO "10" SECONDS SETPOINT internal_EM|=0x4000; ///jump to transition set lcd_clear(); lcd_put_cur(0,0); lcd_send_string("I2C1->CR1"); D=I2C1->CR1 |=0x00; lcd_put_cur(1,0); lcdSendHEX(D,15); goto STEP_UPDATE; ///-----------------------------------TRANSITION 100--------------------------------------------------------// TRANS_100: if (T[0]&0x80000000) {internal_EM|=0x80000000;internal_EM= internal_EM+100;} goto END; ///-----------------------------------STEP 200-------------------------------------------------------------// STEP_200:GPIOD->BSRRH =0x2000; GPIOD->BSRRL =0x1000; T[1]|=0x40000000;///SWITCH ON TIMER T[1]=T[1]&0xFFFFC000;///SET TIMER TO "0" SETPOINT T[1]|=10;///SET TIMER TO "10" SECONDS SETPOINT internal_EM|=0x4000; ///jump to transition set lcd_put_cur(0,0); lcd_send_string("What? "); D=RCC->CR |=0x00; lcd_put_cur(1,0); lcdSendHEX(D,15); goto STEP_UPDATE; ///-----------------------------------TRANSITION 200--------------------------------------------------------// TRANS_200:if (T[1]&0x80000000) {internal_EM|=0x80000000;internal_EM= internal_EM+100;} goto END; ///-----------------------------------STEP 300-------------------------------------------------------------// STEP_300:GPIOD->BSRRH =0x4000; GPIOD->BSRRL =0x2000; T[2]|=0x40000000;///SWITCH ON TIMER T[2]=T[2]&0xFFFFC000;///SET TIMER TO "0" SETPOINT T[2]|=10;///SET TIMER TO "10" SECONDS SETPOINT internal_EM|=0x4000; ///jump to transition set goto STEP_UPDATE; ///-----------------------------------TRANSITION 300--------------------------------------------------------// TRANS_300:if (T[2]&0x80000000) {internal_EM|=0x80000000;internal_EM= internal_EM+100;} goto END; ///-----------------------------------STEP 400-------------------------------------------------------------// STEP_400:GPIOD->BSRRH =0x8000; GPIOD->BSRRL =0x4000; T[3]|=0x40000000;///SWITCH ON TIMER T[3]=T[3]&0xFFFFC000;///SET TIMER TO "0" SETPOINT T[3]|=10;///SET TIMER TO "10" SECONDS SETPOINT internal_EM|=0x4000; ///jump to transition set goto STEP_UPDATE; ///-----------------------------------TRANSITION 400--------------------------------------------------------// TRANS_400:if (T[3]&0x80000000) {internal_EM|=0x80000000;internal_EM= internal_EM-300 ;} goto END; ///-----------------------------------STEP UPDATE-------------------------------------------------------// STEP_UPDATE:Temp_EM=internal_EM&0x3FFF;///read requested step number internal_EM=((internal_EM&0xC000FFFF)+ (Temp_EM<<16));///update step number ///-----------------------------------RETURN DATA-------------------------------------------------------// END:EM[i]=internal_EM; } где int T[10];///where [XX] (XX-1)=number of used timers in code /// bits[13-0] - set time (max 16383),bit [14] -spare ,bit [15] - pause if set /// bits[29-16] - actual time (max 16383),bit [30] -enable if set,bit [31] -complete if set ///-----------------------------------EM`s VARIABLES----------------------------------------------------// int internal_EM;/// bits[13-0] - requested step (max 16383),bit [14] - jump to transition if set/else to step,bit [15] -Auto mode if set/else Manual ///bits[29-16] - present step (max 16383),bit [30] -Forse to complete if set/else normal,bit [31] -status complete if set; И проход через ШАГ идет один раз, а через транзишн, может идти многократно.. Спасибо - буду "курить тему".. Изменено 4 июня, 2021 пользователем UAKIVSO добавить код Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться