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

I2C самопал, возможно ли это?

Итак, причина, по которой я пытаюсь наваять что нить по 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);
}

 

 

Понимаю, что многие скажут, что бред, но может это возможно заставить работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем реализовать софтово то, что есть аппаратно? Особенно на таком жирном МК! Он же у вас находится в итоге большую часть времени в блокирующем ожидании. Нехорошо это. Хотя бы реализуйте конечный автомат с поллингом или же (еще лучше) - на таймере с ногодрыгом по DMA.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Софтварно все пишется и довольно легко, но только вот нужно уметь программировать, постарайтесь счесть за инструкцию к действию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Eddy_Em сказал:

Зачем реализовать софтово то, что есть аппаратно? Особенно на таком жирном МК! Он же у вас находится в итоге большую часть времени в блокирующем ожидании. Нехорошо это. Хотя бы реализуйте конечный автомат с поллингом или же (еще лучше) - на таймере с ногодрыгом по DMA.

I2C лишь шаг к пониманию как дергать ножками - цель профинет

 

касаемо ожидания - оптимизация будет позже, сначала нужно, дабы заработало

1 час назад, rkit сказал:

Софтварно все пишется и довольно легко, но только вот нужно уметь программировать, постарайтесь счесть за инструкцию к действию.

Возможно весь код поможет (выложить?), но хотелось бы пинок в правильном направлении ;) где я не так что-то накрутил

И да, программировать на стл в сименсе могу, но си как то тяжко заходит - многого не знаю. Стилистика написания конечно корявая и не оптимизированная, но как только начнёт фурычить, то потрачу пару неделек на «причесывание и оптимизацию» «школьного кода»

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 minutes ago, UAKIVSO said:

но хотелось бы пинок в правильном направлении

Edit -> Format document

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 — моветон.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, не нужно тратить пару неделек на оптимизацию кода, который можно сразу правильно написать за день.

Вот так код должен выглядеть. Замени определения все тела scl_* sda_* на обращения к регистрам, если хочется именно так.

https://github.com/liyanboy74/soft-i2c/blob/main/i2c_sw.c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Логический анализатор подключите и отлаживайте свой ногодрыг, поглядывая на диаграммы I2C-шины.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Итак, благодаря "волшебным пендалям" в заданном направлении получил аппаратный 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 милисекунд

image.thumb.png.51b90ba2e2edb284b1da601c4fbb85dd.png

 

Понимаю, что можно оптимизировать возможно в 2-4 раза код=меньше кратно будут отсылаться данные, но вот все одно это будут 2-3 милисекунды...

 

А жто много. для контоллера, который ничего не делает и столько времени тратит на пересылку ТОЛЬКО..

 

Вот поэтому и хотелось ручной ногодрыг или что-то такое, когда время, между позитивными флагами SCL будет использоваться для проходов программы.

Прерывания не сильно хотелось бы внедрять = нет веры в си компилятор, не понятно, все ли гладко в итоге будет.. 

 

 

Собственно требуется от ГУРУ еще какой нить пинок в нужном направлении.. Может дадите толчок !?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Quote

Прерывания не сильно хотелось бы внедрять = нет веры в си компилятор

Что за компилятор то у Вас такой страшный что Вы его боитесь? Уверен, что через пару лет разработки Вы перечитаете своё сообщение и так же, как я, улыбнётесь. Чтобы уйти от блокирующего кода Вам могут помочь аппаратные средства МК: прерывания, DMA; программные средства: операционная система, машина состояний (конечный автомат). Прерывания, пожалуй, самый простой из доступных способов.

И ещё, совет. Избегайте "магических чисел" при работе с регистрами периферии МК. Используйте макроопределения битов из файла "stm32F407xx.h" для своего процессора. Например для строки

I2C1->CR1 |= 0x01; ///PE: Peripheral enable
I2C1->CR1 |= I2C_CR1_PE; ///PE: Peripheral enable

Будет легче читать код и искать ошибки

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использую EmBitz 1.11, так как халявный...

возможно Вы правы, буду улыбаться со своих постов.

Про магические числа понял, учту...

Ну а если прерывания, то как с ними быть? К примеру делаю старт - пишу на дисплей что-то, отправляю в регистр адрес, далее на свой код перехожу...

появляется прерывание по получению адреса.. 

в разных обработчиках разные куски тулить? 
туплю я чего-то, не складывается картинка.. :(

 

Сори, что значит конечный автомат? Не совсем понимаю что это?
 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вектор прерывания у модуля I2C один, следовательно и функция-обработчик будет одна, на все возможные события. Для мастер-передатчика надо будет обрабатывать следующие события (* я с I2C на F4xx семействе не работал, могут кое-где соврать).

image.thumb.png.e4c83356b6e3dcec16b3a7d96e54d26a.png

Следовательно в основной программе инициировали передачу посредством старт-условия, занялись другими делами. Сгенерировалось прерывание, в обработчике анализируете флаги статусного 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;
}

Читаемости коду такие конструкции не прибавляют, но это плата за однопоточность.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

идея понятна, я по такой сути делаю ЕМ, как в 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;

 

И проход через ШАГ идет один раз, а через транзишн, может идти многократно..

 

Спасибо - буду "курить тему".. 

Изменено пользователем UAKIVSO
добавить код

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...