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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

HF_Cat писал(а):Не нашёл как оформить функцию, которая бы вмещала обе части программы по индикации на "дисплей". Подскажите как или скажите где почитать.
СПС

Не нужно стараться делать универсальные функции- нужно, чтобы функция выполняла одну конкретную задачу, но так хорошо, чтобы к ней никаких претензий не было.
Аватара пользователя
Apparatchik
Держит паяльник хвостом
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

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

Сообщение Apparatchik »

HF_Cat писал(а):Пишу прогу на Си в AVR Studio 4 - динамическую индикацию на 7сегм-ных индикаторах. Нужно оформить вывод данных на этот дисплей как отдельную функцию. Часть программы по выводу на дисплей выполняется в прерывании по OVF_T0, а часть - вне прерывания. Не нашёл как оформить функцию, которая бы вмещала обе части программы по индикации на "дисплей". Подскажите как или скажите где почитать.
СПС

По прерыванию выводить на экран некий массив, а в функции просто заполнять этот массив.
«И всё-таки она вертится!»
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

Приветствую, господа.
Изучал очередную учебную программку для Attiny13A, и появился очередной глупый вопрос.
Программа считывает значения с трех входов АЦП и выдает на три выхода сигнал ШИМ, скважность которого зависит от значений с АЦП.
Код:
Спойлер

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

#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU 9600000UL
#include<util/delay.h>

//Прототипы функций
void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status);
unsigned char read_adc(unsigned char channel);

//Глобальные переменные
volatile unsigned char e;
volatile unsigned char pwm[3]={255,255,255};


int main(void)
{


   DDRB  &= ~((1<<3)|(1<<4)|(1<<5));//Входы АЦП
   
   //В начальный момент светодиоды выключены
   DDRB |=  (1<<0|1<<1|1<<2);
   PORTB |= (1<<0)|(1<<1)|(1<<2);
   
   //ADC init
   
   ADMUX =  0b00100000; //ADC0 (default),ADLAR,VCc
   ADCSRA = 0b10000010; //Предделитель 4
   
   //Инициализация таймера
   TCCR0A = 0x00;
   TCCR0B = 0x01;//Без предделителя
   TIMSK0 = 1<<TOIE0;//Прерывание по переполнению таймера включено
   sei();//Включены глобальные прерывания

   while(1)
   {   
   
      pwm[0]=read_adc(0);
      pwm[1]=read_adc(2);
      pwm[2]=read_adc(3);
      
      _delay_ms(2);//Просто небольшая задержка   
   
   }

   

}


//Функция обработки прерывания по переполнению Timer 0
ISR(TIM0_OVF_vect)
{
   
   //Переменной e осуществляется выбор уровня работы ШИМ
   //Имеется 256 уровней для e от 0 до 255
   //0 - полностью включен и 255 полность выключен
   
   if(e==255)
   {
      e=0;
      PORTB |= (1<<0)|(1<<1)|(1<<2);
   }

   abc(pwm[0],pwm[1],pwm[2],e);
   
   e++;
   
}


//Эта функция вызывается для включения светодиодов в 
//определенный период работы ШИМ.
void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status)
{

   if((status==a))
   {
      PORTB&= ~(1<<0);
   }
   if((status==b))
   {
      PORTB&= ~(1<<1);
   }
   if((status==c))
   {
      PORTB&= ~(1<<2);
   }
   
}

//Эта функция считывает значение на выбранном канале АЦП
unsigned char read_adc(unsigned char channel)
{
   
   unsigned char k;
   unsigned int adcvalue=0;
   ADMUX = ADMUX&(0b11111100); //Сброс битов выбора канала
   ADMUX |= channel;    
   
   //Игнорируется первое чтение после смены канала
   ADCSRA |= 1<<ADSC;
   while(ADCSRA&(1<<ADSC));//Ждем
   adcvalue=ADCH;
   adcvalue=0;//Игнорирование
   for(k=0;k<=7;k++)
   {
      ADCSRA |= 1<<ADSC;
      while(ADCSRA&(1<<ADSC));//Ждем
      adcvalue += ADCH;
   }
   return (adcvalue>>3); //Деление на 8
   
}

В функции обработки прерывания используется переменная unsigned char e. Но нигде в программе я не увидел установки начального значения этой переменной. Сразу идет проверка, равна ли переменная 255 и тд. по программе. А что в нее записано в первый момент времени непонятно. Это нормально или очередное издевательство авторов программы над стандартом?
We do what we must because we can (c) GLaDOS
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

baron_P писал(а):В функции обработки прерывания используется переменная unsigned char e. Но нигде в программе я не увидел установки начального значения этой переменной.

Это глобальная переменная, а глобальные переменные (если им не присваивается другое значение) автоматически при старте обнуляются.

Кстати то же самое происходит и с неглобальными переменными объявленными как static.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение urry »

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

char temp[3];

temp[0]=read_adc(0);
temp[1]=read_adc(2);
temp[2]=read_adc(3);
cli();
rwm[0]=temp[0];
rwm[1]=temp[1];
rwm[2]=temp[2];

sei();
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

Спасибо, с переменной понятно. А с контролем готовности значений ацп, перед отработкой прерывания - не совсем.
Такой код:

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

unsigned char temp[3];

temp[0]=read_adc(0);
temp[1]=read_adc(2);
temp[2]=read_adc(3);
cli();
rwm[0]=temp[0];
rwm[1]=temp[1];
rwm[2]=temp[2];

sei();
предотвратит ситуацию, когда прерывание наступает между присвоением, например, rwn[0] и rwn[1] измеренных значений, т.е. в функции прерывания используется часть массива с устаревшими значениями, считанными с АЦП в прошлом цикле. А сама функция считывания значений на входе АЦП (read_adc()) может быть прервана в любой момент, но на работу программы это влияния оказыать не должно. Правильно?
We do what we must because we can (c) GLaDOS
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение urry »

да, в данной ситуации это некритично - прочитается всего лишь старое значение - но представим ситуацию, если вы будете усреднять значение ацп - скажем, сумму 4 значений, чтобы потом ее разделить на 4 - и по прерыванию наверх уйдет сумма, а не результат деления. То же касается инкремента, декремента и т.д. Такие варианты нужно предусматривать заранее, чтобы не было потом неприятных сюрпризов.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

как в данном случае наверх может уйти сумма результатов преобразований?
Ставим плюсы: )
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

urry писал(а): и по прерыванию наверх уйдет сумма, а не результат деления.

ibiza11 писал(а):как в данном случае наверх может уйти сумма результатов преобразований?

Если только для расчета использовать одну и ту же переменную, но лично я бы так не стал делать.
urry писал(а):Такие варианты нужно предусматривать заранее, чтобы не было потом неприятных сюрпризов.
Эт правильно :) :beer:
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

vitalik_1984 писал(а):Если только для расчета использовать одну и ту же переменную
ну так исходник же есть. там не используется одна и та же переменная. в данном случае сумма наверх никак не уйдет.
Ставим плюсы: )
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

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

Сообщение baron_P »

В этой программе такой кусок кода не нужен, но, вообще, помнить о не вовремя выскочившем прерывании стоит всегда - так можно переформулировать.
Вопросы кончились, пойду следующий девайс паять/программить :)
We do what we must because we can (c) GLaDOS
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение urry »

я имел в виду атомарный доступ и критические секции - не знаю никого, кто бы на этом не накололся
http://www.pic24.ru/doku.php/osa/articl ... 1%83%D0%BF
dimka86
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вт фев 21, 2012 15:05:12

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

Сообщение dimka86 »

доброго времени суток поскажите как из этого кода сделать функцию,которая возвращает строку 'txxxxxxe' символ 't' можно было заменить на любой другой, строка переменная получается путем преобразования числа в строку

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

                    for (q=0;strlen(str1)+1;q=q+1)
                    {
                    if(q==strlen(str1)+1){send_str[q]='e';send_str[q+1]='\0';break;}
                    if(q==0)send_str[q]='f';
                    else
                    send_str[q]=str1[q-1];
                    }
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

возвращает строку 'txxxxxxe'
А что за xxxxx ? Если это число, то в Си уже есть такая функция - называется sprintf.
dimka86
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вт фев 21, 2012 15:05:12

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

Сообщение dimka86 »

xxxxx это строка полученная из числа 0-65535.sprintf при использовании занимает много памяти
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

занимает много памяти
Много - это сколько ? Какой памяти ? И у кого занимает ?
Думаете Ваш вышеприведённый кусок пипец как оптимален ? :))
dimka86
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Вт фев 21, 2012 15:05:12

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

Сообщение dimka86 »

в flash памяти avr я не говорю что этод код оптимален и является эталоном явно нет но он работает если есть мысль по оптимизации всегда рад совету тем более я не очень силен в программировании можно сказать'молодо зелено' просто этод код должен выполнятся 8 раз вот поэтому и хочу преобразовать его в функцию
Slavok47
Встал на лапы
Сообщения: 144
Зарегистрирован: Ср дек 14, 2011 08:12:49

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

Сообщение Slavok47 »

Привет всем! решил изучать С и сразу же столкнулся с вопросом о назначении портов вывод/ввод, Например:

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

bit oldstate;                       // Old state flag

void main() {

  DDB0_bit = 0;                     // Set PB0 pin as input

  DDRC  = 0xFF;                     // Configure PORTC as output
  PORTC = 0xAA;                     // Initial PORTC value
 
  oldstate = 0;
 
  do {
    if (Button(&PINB, 0, 1, 1)) {   // Detect logical one
      oldstate = 1;                 // Update flag
    }
    if (oldstate && Button(&PINB, 0, 1, 0)) { // Detect one-to-zero transition
      PORTC = ~PORTC;               // Invert PORTC
      oldstate = 0;                 // Update flag
    }
  } while(1);                       // Endless loop
}

Судя по строке DDB0_bit = 0; // Set PB0 pin as input на порт PB0 можно посадить кнопку, и она работает, а если мне нужно на PB1? DDB1_bit = 0; не работает..
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

DDB0_bit, скорее всего, где-то задефайнен.
Какая среда разработки ? Возможно, в ней есть работа с битами. Если нет, то обращайтесь через маскугде x - номер бита.

Так-же погуглите "Битовые операции в Си".
Slavok47
Встал на лапы
Сообщения: 144
Зарегистрирован: Ср дек 14, 2011 08:12:49

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

Сообщение Slavok47 »

Аlex писал(а):Какая среда разработки ?

mikroC
Ответить

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