Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Есть у меня switch case состоящая из 10 case и таких конструкций несколько
Не проще ли пересмотреть структуру программы - массив или индексный переход?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

WiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны
только при условии, что тип переменной в switch соответствует enum
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Не проще ли пересмотреть структуру программы - массив или индексный переход?
А можно по подробнее ?

Это я делаю протокол I2C Без delay_us

при переходе с одного case на другое выполнится автоматически задержка.
пока сделал до ASK
примерно это выглядит так.
Спойлер

Код: Выделить всё

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
      switch(t1){
            case EXIT:{break;} //  Передачик выключен       
//------------START--------------------      
            case START:{
                SDA_1
                SCL_1
                t1=START_1;                  
                break;
            }
            case START_1:{
                SDA_0
                t1=START_1; 
                break;
            }
            case START_2:{
                SCL_0
                t1=SEND; 
                break;
            }                           
//------------Send--------------------
            case SEND:{
            //---------- даные  data
                flag_I2C=data&0x80;
                data=data<<1;
            //---------- данные пуст ?    
                if(data==0){
                    t1=ASK;           
                }
                else{
                    t1=SEND_1;
                }
            //-----------выставляем bit0 на линию------                
                if(flag_I2C==0x80){
                    SDA_1  
                }
                else{
                    SDA_0
                }
                break;
            }
            case SEND_1:{
                SCL_1
                t1=SEND_2; 
                break;
            }
            case SEND_2:{
                SCL_0
                t1=SEND;          //  циклически передаём данные
               break;
            }
//------------ASK--------------------            
            case ASK:{
                ////////////////////////////////////SDA=IN
                t1=ASK_1; 
                break;
            }
            case ASK_1:{
                SCL_1
                if(SDA==0){
                    t1=ASK_2; // идём дальше
                }
                else{
                    //ошибка
                }
                break;
            }
            case ASK_2:{
                SCL_0
                t1=ASK_3; 
                break;
            }
            case ASK_3:{
                if(SDA==1){
                    //t1=ASK_2 // идём дальше   добавить суловия куда идти
                    //SDA=out
                }
                else{
                    //ошибка
                }
                break;
            }
//------------STOP--------------------                                                                                       
            case STOP:{
                SDA_0
                SCL_1
                t1=STOP_1;                  
                break;
            }
            case STOP_1:{
                SDA_1
                t1=EXIT;                  
                break;
            }
      }
TCNT2=DELAYX;
TCNT2=0xFA;
}

Реклама
Эиком - электронные компоненты и радиодетали
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

pokk писал(а):А можно по подробнее ?
Там вариантов много. Например можно использовать массив указателей на функции, если параметры в CASE у вас идут по порядку. Либо алгоритмы работы со списками, и прочее.
Конкретно как сейчас вам лучше организовать - не готов ответить.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

pokk, у вас на метку START_2 код никогда не попадет) поправьте обработчик START_1.
а так все ок.
я бы писал так:

Код: Выделить всё

typedef enum{
	START = 0,
	START_1,
	START_2,
	START_3,
	....
} mode_t;
mode_t Mode;

interrupt [TIM2_OVF] void timer2_ovf_isr(void) { 
  TCNT2=DELAYX;  // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
  
  switch(Mode){
	case START:
	 ....
	 break;
	 
	case START_1:
	 ....
	 break;
	
	default:
	 ....
	 break;
  }
}
Ставим плюсы: )
Реклама
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

ibiza11 писал(а):TCNT2=DELAYX; // это в самом начале обработчика, чтобы задержка не зависела от времени выполнения switch-case
что-то не понял как задержка зависит swith-case? задал частоту 100 Khz и всё главное что бы в прерывание успело выполнится за данный период.
а где задавать частоту какая разница в любом же случает он выполнит всё прерывание.
Я вообще специально вниз поставил что бы можно было изменить задержку.
типа так:

Код: Выделить всё

interrupt [TIM2_OVF] void timer2_ovf_isr(void) {

 
  switch(Mode){
   case START:
   DELAYX=5 мк
    ....
    break;
   
   case START_1:
    ....
    break;

   case STOP:
   DELAYX=255 мк
    break;

  
   default:
    ....
    break;
  }

  TCNT2=DELAYX; 
}
WiseLord писал(а):Ещё, ЕМНИП, при замене #define на enum компилятор в случае перебора по case ругнётся в случае, если не все варианты перебраны (при отсутствии default, конечно). Тоже какой-никакой контроль.
сделал как предложил ibiza11 пару case закомментировал и нечего от CodeVision не увидел.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

pokk писал(а):что-то не понял как задержка зависит swith-case?
прерывание таймера происходит по его переполнению. т.е. значение TCNT2 в этот момент = 0.
После входа в прерывание, таймер не останавливается, и, в зависимости от предделителя таймера, может насчитать еще несколько импульсов во время выполнения обработчика прерывания.
Операция TCNT2=DELAYX; предназначена для того, чтобы сместить начальное значение TCNT2 относительно нуля, тем самым определяя кол-во тиков таймера до момента его прерывания.
Для примера: TCNT2 = 100 - определит задержку равную (256-100)=156 тикам таймера при условии, что в начальный момент значение таймера = 0, поскольку таймер (в данном случае таймер №2) переполнится после значения 255.
Но, поскольку эта операция может быть произведена в момент, когда значение TCNT2 не равно нулю, может появиться погрешность в бОльшую сторону равная значению TCNT2 в момент совершения операции присвоения. Поэтому, чем раньше вы ее произведете, тем меньше вероятность того, что возникнет погрешность.
У любой инструкции есть время выполнения, а поскольку switch-case также является инструкцией контроллера, то и у нее есть время выполнения. Следовательно пока выполняется switch-case значение таймера может стать отличным от нуля.
Все это можно проверить в симуляторе или попытаться рассчитать, имея значение предделителя таймера.
Ставим плюсы: )
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Благодарю за помощь.
Я упустил момент, что таймер не останавливается после входа в прерывание.
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

А как описать, что мне нужен массив из 11 таких элементов:

Код: Выделить всё

struct {
  unsigned char image : 8;
  unsigned char brightness : 3;
  unsigned char blink : 1;
}symbol;
Вернее, у меня есть такой массив: volatile unsigned int videobuff[11], но мне хочется, чтобы когда я переписываю младший байт - старший не менялся бы. Вернее я мог бы решать, что хочу переписать: младший байт, старший или только один бит установить/сбросить.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ну, в подобных случаях я поступаю так:

Код: Выделить всё

typedef struct {
  unsigned char image : 8;
  unsigned char brightness : 3;
  unsigned char blink : 1;
}symbol_t;

symbol_t videobuf[11];

// доступ:
vodeobuf[5].blink = 0;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 70
Зарегистрирован: Пт янв 31, 2014 17:08:09

Сообщение Мелкий пакостник »

Доброго времени суток. Хочу научится программировать, с чего начать? :beer:
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

С компа, на МК сразу писать смысла особого нет :)
http://lib.ru/CTOTOR/starterkit.txt
На название внимания не обращайте, книга действительно хорошая для начинающих.
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Товарищи коты, помогите пожалуйста. Есть функция, в которую я должен передать n-й элемент массива. Пытаюсь передать через указатель. Передаваемый элемент функция вроде бы видит, но увеличивать адрес указателя у меня не получается. Пробовал по-разному, это один из вариантов. Подскажите пожалуйста, как правильно

Код: Выделить всё

static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len)
{
	while (M95_read_SR() & M95_WIP);

	M95_CS_0();
	SPI1_write_byte(M95_WREN);
	M95_CS_1();
	while (M95_read_SR() & M95_WIP);
	while ((M95_read_SR() & M95_WEL) == 0);

	M95_CS_0();

    SPI1_write_byte(M95_WRITE);
    SPI1_write_byte((addr >> 8) & 0xFF);
    SPI1_write_byte(addr & 0xFF);

	for (uint8_t i = 0; i < len; i++)	{
		SPI1_write_byte(buffer);
		(*buffer)++;
	}

	M95_CS_1();
	while (M95_read_SR() & M95_WIP);
}
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

указатель сдвигается так:

Код: Выделить всё

buffer++;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

я пробовал так:

Код: Выделить всё

for (uint8_t i = 0; i < len; i++)   {
      SPI1_write_byte(buffer);
      buffer++;
   }
но тогда получается, что я увеличиваю не адрес, а значение первого элемента buffer. т.е. если передаю в функцию массив buff[] = {AA, 00, 00, 00....}, на выходе из этой функции у меня выходит {AA, AB, AC, AD....}
если делаю так:

Код: Выделить всё

for (uint8_t i = 0; i < len; i++)   {
      SPI1_write_byte(*buffer);
      buffer++;
   }
то на выходе у меня совсем мусор выходит. а в предыдущем случае хоть первый элемент ловило
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

как определена эта функция: SPI1_write_byte(buffer);? я так понимаю, именно она отправляет ваши байты? может, вы неправильно ей параметр передаете, потому что между SPI1_write_byte(buffer); и SPI1_write_byte(*buffer); большая разница: вы пробовали и так и этак - разве компилятор не варнингует у вас?!

да и каким образом вы массив передаете в эту функцию: static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len) - может, проблема еще "выше"?

что касается указателя, то в вашем случае:
buffer++ - инкремент УКАЗАТЕЛЯ
*buffer++ - инкремент указателя
(*buffer)++ инкремент ПО УКАЗАТЕЛЮ, т.е. элемента массива
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

функция передачи по SPI:

Код: Выделить всё

void SPI1_write_byte(uint8_t b)
{
	uint8_t temp;
	SPI_I2S_SendData(SPI1, b);
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
	temp = SPI_I2S_ReceiveData(SPI1);
}
пробовал делать так:

Код: Выделить всё

uint8_t temp1 = *buffer;
SPI1_write_byte (temp1);
тоже мешанина на выходе.

функцию M95_write(...) я вызываю так:

Код: Выделить всё

for (uint8_t i = 0; i < 8; i++)	{
	M95_write(DIS_PAGE_START + (32 * i), (APP_Tx_Buffer[4 + (32 * i)]), 32);
}
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

функция определена как static void M95_write(uint16_t addr, uint8_t* buffer, uint8_t len), то есть второй параметр - УКАЗАТЕЛЬ НА БАЙТ

вызываете вы ее так:M95_write(DIS_PAGE_START + (32 * i), (APP_Tx_Buffer[4 + (32 * i)]), 32); то есть вторым параметром передаете ей БАЙТ

варнинг компилятора есть на вызов функции? должен быть бы по идее...

правильно вызывать так:M95_write(DIS_PAGE_START + (32 * i), &APP_Tx_Buffer[4 + (32 * i)], 32);

ну а затем в теле функции уже так:

Код: Выделить всё

for (uint8_t i = 0; i < len; i++)   {
      SPI1_write_byte(*buffer++);
   }
или так:

Код: Выделить всё

for (uint8_t i = 0; i < len; i++)   {
      SPI1_write_byte(buffer[i]);
   }
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Точно:) спасибо большое!
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Ответить

Вернуться в «Разные вопросы по МК»