Не нужно стараться делать универсальные функции- нужно, чтобы функция выполняла одну конкретную задачу, но так хорошо, чтобы к ней никаких претензий не было.HF_Cat писал(а):Не нашёл как оформить функцию, которая бы вмещала обе части программы по индикации на "дисплей". Подскажите как или скажите где почитать.
СПС
Вопросы по С/С++ (СИ)
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
- Реклама
- Apparatchik
- Держит паяльник хвостом
- Сообщения: 908
- Зарегистрирован: Вс май 23, 2010 13:55:42
- Откуда: Украина, Александрия
Re: Вопросы по С/С++ (СИ)
По прерыванию выводить на экран некий массив, а в функции просто заполнять этот массив.HF_Cat писал(а):Пишу прогу на Си в AVR Studio 4 - динамическую индикацию на 7сегм-ных индикаторах. Нужно оформить вывод данных на этот дисплей как отдельную функцию. Часть программы по выводу на дисплей выполняется в прерывании по OVF_T0, а часть - вне прерывания. Не нашёл как оформить функцию, которая бы вмещала обе части программы по индикации на "дисплей". Подскажите как или скажите где почитать.
СПС
«И всё-таки она вертится!»
- baron_P
- Нашел транзистор. Понюхал.
- Сообщения: 183
- Зарегистрирован: Вт сен 14, 2010 23:07:10
- Откуда: Ростов
Re: Вопросы по С/С++ (СИ)
Приветствую, господа.
Изучал очередную учебную программку для Attiny13A, и появился очередной глупый вопрос.
Программа считывает значения с трех входов АЦП и выдает на три выхода сигнал ШИМ, скважность которого зависит от значений с АЦП.
Код:
В функции обработки прерывания используется переменная unsigned char e. Но нигде в программе я не увидел установки начального значения этой переменной. Сразу идет проверка, равна ли переменная 255 и тд. по программе. А что в нее записано в первый момент времени непонятно. Это нормально или очередное издевательство авторов программы над стандартом?
Изучал очередную учебную программку для 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
}
We do what we must because we can (c) GLaDOS
Re: Вопросы по С/С++ (СИ)
Это глобальная переменная, а глобальные переменные (если им не присваивается другое значение) автоматически при старте обнуляются.baron_P писал(а):В функции обработки прерывания используется переменная unsigned char e. Но нигде в программе я не увидел установки начального значения этой переменной.
Кстати то же самое происходит и с неглобальными переменными объявленными как static.
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
статик и есть глобальная переменная, только с ограниченной областью видимости.
Ее, кстати, инициировать бы вручную при создании. Я бы задумался над отсутствием критической секции в проге -
прерывание может наступить в любой момент, когда значение с ацп еще не готово.
Что-то такое дописать
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();
Ее, кстати, инициировать бы вручную при создании. Я бы задумался над отсутствием критической секции в проге -
прерывание может наступить в любой момент, когда значение с ацп еще не готово.
Что-то такое дописать
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: Вопросы по С/С++ (СИ)
Спасибо, с переменной понятно. А с контролем готовности значений ацп, перед отработкой прерывания - не совсем.
Такой код: предотвратит ситуацию, когда прерывание наступает между присвоением, например, rwn[0] и rwn[1] измеренных значений, т.е. в функции прерывания используется часть массива с устаревшими значениями, считанными с АЦП в прошлом цикле. А сама функция считывания значений на входе АЦП (read_adc()) может быть прервана в любой момент, но на работу программы это влияния оказыать не должно. Правильно?
Такой код:
Код: Выделить всё
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();We do what we must because we can (c) GLaDOS
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
да, в данной ситуации это некритично - прочитается всего лишь старое значение - но представим ситуацию, если вы будете усреднять значение ацп - скажем, сумму 4 значений, чтобы потом ее разделить на 4 - и по прерыванию наверх уйдет сумма, а не результат деления. То же касается инкремента, декремента и т.д. Такие варианты нужно предусматривать заранее, чтобы не было потом неприятных сюрпризов.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
как в данном случае наверх может уйти сумма результатов преобразований?
Ставим плюсы: )
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
urry писал(а): и по прерыванию наверх уйдет сумма, а не результат деления.
Если только для расчета использовать одну и ту же переменную, но лично я бы так не стал делать.ibiza11 писал(а):как в данном случае наверх может уйти сумма результатов преобразований?
Эт правильноurry писал(а):Такие варианты нужно предусматривать заранее, чтобы не было потом неприятных сюрпризов.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
ну так исходник же есть. там не используется одна и та же переменная. в данном случае сумма наверх никак не уйдет.vitalik_1984 писал(а):Если только для расчета использовать одну и ту же переменную
Ставим плюсы: )
- baron_P
- Нашел транзистор. Понюхал.
- Сообщения: 183
- Зарегистрирован: Вт сен 14, 2010 23:07:10
- Откуда: Ростов
Re: Вопросы по С/С++ (СИ)
В этой программе такой кусок кода не нужен, но, вообще, помнить о не вовремя выскочившем прерывании стоит всегда - так можно переформулировать.
Вопросы кончились, пойду следующий девайс паять/программить
Вопросы кончились, пойду следующий девайс паять/программить
We do what we must because we can (c) GLaDOS
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
я имел в виду атомарный доступ и критические секции - не знаю никого, кто бы на этом не накололся
http://www.pic24.ru/doku.php/osa/articl ... 1%83%D0%BF
http://www.pic24.ru/doku.php/osa/articl ... 1%83%D0%BF
Re: Вопросы по С/С++ (СИ)
доброго времени суток поскажите как из этого кода сделать функцию,которая возвращает строку '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: Вопросы по С/С++ (СИ)
А что за xxxxx ? Если это число, то в Си уже есть такая функция - называется sprintf.возвращает строку 'txxxxxxe'
Re: Вопросы по С/С++ (СИ)
xxxxx это строка полученная из числа 0-65535.sprintf при использовании занимает много памяти
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Много - это сколько ? Какой памяти ? И у кого занимает ?занимает много памяти
Думаете Ваш вышеприведённый кусок пипец как оптимален ?
Re: Вопросы по С/С++ (СИ)
в flash памяти avr я не говорю что этод код оптимален и является эталоном явно нет но он работает если есть мысль по оптимизации всегда рад совету тем более я не очень силен в программировании можно сказать'молодо зелено' просто этод код должен выполнятся 8 раз вот поэтому и хочу преобразовать его в функцию
Re: Вопросы по С/С++ (СИ)
Привет всем! решил изучать С и сразу же столкнулся с вопросом о назначении портов вывод/ввод, Например:
Судя по строке DDB0_bit = 0; // Set PB0 pin as input на порт PB0 можно посадить кнопку, и она работает, а если мне нужно на PB1? DDB1_bit = 0; не работает..
Код: Выделить всё
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
}
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
DDB0_bit, скорее всего, где-то задефайнен.
Какая среда разработки ? Возможно, в ней есть работа с битами. Если нет, то обращайтесь через маскугде x - номер бита.
Так-же погуглите "Битовые операции в Си".
Какая среда разработки ? Возможно, в ней есть работа с битами. Если нет, то обращайтесь через маску
Код: Выделить всё
&(1<<x)
Так-же погуглите "Битовые операции в Си".
Re: Вопросы по С/С++ (СИ)
mikroCАlex писал(а): Какая среда разработки ?


