Програмирование pic на СИ.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Програмирование pic на СИ.
Самый хороший учитель - это время. Правильно понимаете, что со временем и опыт придёт и код будет становиться более "прозрачным". ТАк что, не переживайте по этому поводу, просто занимайтесь любимым делом и всё 
- Реклама
-
Darkmaster
- Встал на лапы
- Сообщения: 137
- Зарегистрирован: Вс окт 11, 2009 09:54:59
- Откуда: Пенза
Re: Програмирование pic на СИ.
Здравствуйте дамы и господа 
разбирался я тут с АЦП в pic'ах ..и вот застрял на преобразовании результата Ацп в вольты.
А именно :для перевода нам надобно Результат Ацп умножить на Опорное напряжение и это в Разделить на количество отсчетов.(ADC*Uоn/1023)типа того.
Нужно получить результат в вольтах формата х.хх
переменную какого типа следует использовать для хранения результата и как получить 2 (или сколько нужно) знака после запятой?
Вроде понятно описал проблему )
читал статьи-уроки -это ужос а не уроки.То берут некие значения без пояснении и ссылок на что либо то еще чего.
Надеюсь на вашу помощь Коты
Котам пасибо
ответ найден и вроде понятно стало .будем шкодить
разбирался я тут с АЦП в pic'ах ..и вот застрял на преобразовании результата Ацп в вольты.
А именно :для перевода нам надобно Результат Ацп умножить на Опорное напряжение и это в Разделить на количество отсчетов.(ADC*Uоn/1023)типа того.
Нужно получить результат в вольтах формата х.хх
переменную какого типа следует использовать для хранения результата и как получить 2 (или сколько нужно) знака после запятой?
Вроде понятно описал проблему )
читал статьи-уроки -это ужос а не уроки.То берут некие значения без пояснении и ссылок на что либо то еще чего.
Надеюсь на вашу помощь Коты
Котам пасибо
ответ найден и вроде понятно стало .будем шкодить
Интересная,однако,штука
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Програмирование pic на СИ.
Если заранее известно количество знаков после запятой, то лучше использовать целочисленные типы. А результат хранить как умноженный на 10 в степени кол-ва разрядов. Т.е. при 1 знаке после запятой - *10, при 2-ух знаках - *100, при 3-ёх - *1000, и т.д...
-
Darkmaster
- Встал на лапы
- Сообщения: 137
- Зарегистрирован: Вс окт 11, 2009 09:54:59
- Откуда: Пенза
Re: Програмирование pic на СИ.
пасибо.Аlex писал(а):Т.е. при 1 знаке после запятой - *10, при 2-ух знаках - *100, при 3-ёх - *1000, и т.д...
именно с этим разобрался.Целые рулят.
Ишо бы оптимизировать умножения/деление
Интересная,однако,штука
-
driver_gv
- Потрогал лапой паяльник
- Сообщения: 399
- Зарегистрирован: Сб авг 08, 2009 23:02:57
- Откуда: Ростов-на-Дону
- Контактная информация:
Re: Програмирование pic на СИ.
Умножить на 10 - это три сдвига влево и два сложения для PIC16 , у 18-х есть аппаратный умножитель.
__________________
Все, что нельзя запрограммировать на ассемблере, приходится паять
Все, что нельзя запрограммировать на ассемблере, приходится паять
- Реклама
-
Darkmaster
- Встал на лапы
- Сообщения: 137
- Зарегистрирован: Вс окт 11, 2009 09:54:59
- Откуда: Пенза
Re: Програмирование pic на СИ.
да,читал об этом.Компилятор Hi-tech 9.71..pic16.интересно он (компилятор) тоже сдвиг делает или нет ,может кто в курсе ? (то есть я пишу 5/100 а он автоматом сдвигает.)driver_gv писал(а): для PIC16
засада получается..
Подумал я было
do
variable=variable>>10
while(variable2<количество раз)
но че то ни так ни сяк..это вместо деления на 1000
можно ли по такому принципу как то?
Интересная,однако,штука
-
electronik_tver
- Открыл глаза
- Сообщения: 54
- Зарегистрирован: Пн авг 05, 2013 12:18:46
Re: Програмирование pic на СИ.
Подскажите пож как лучше сделать, есть устройство на pic16f877, хайтек, с, в программе необходимо отсчитывать параллельно несколько временных участков, с достаточно немаленькими величинами, например на время горения экрана после последней нажатой кнопки 30сек, время на закрытие задвидки 4мин, время работы механизма 10мин и тд, трех таймеров на все не хватит да и делители дикие получаются, устройство уже собрано, речь о реконструкции кода, еще в составе есть часы реального времени, обмен работает, теоретически можно подать секундные импульсы с часов на t0cki и задействовать tmr0, сейчас все работает по принципу узнал на часах время, прибавил нужный отрезок и жду когда это время наступит, но это топорно както, простой пример вдруг время собъется, как вообще пишутся программы с параллельными временными отрзками, хочется красиво сделать, интересует общий подход
Re: Програмирование pic на СИ.
Зависит от дискретности. Если для таких интервалов дискретность в 1 сек. приемлема, то делаете таймер с прерыванием в 1 сек и в обработчике отсчитываете интервалы.
Вот, например, в моём проекте в таймере контролирующем динамическую индикацию попутно отсчитывается частота мигания символов, дребезга клавиатуры и задержка оставленного режима отображения до перехода в основной.
Вот, например, в моём проекте в таймере контролирующем динамическую индикацию попутно отсчитывается частота мигания символов, дребезга клавиатуры и задержка оставленного режима отображения до перехода в основной.
Код: Выделить всё
#pragma interruptlow tmr0routine
void tmr0routine(void) {
[skip]
blink_cnt++;
if (kbddelay != 0) kbddelay--;
if (showdelay != 0) showdelay--;
INTCONbits.TMR0IF = 0;
}-
electronik_tver
- Открыл глаза
- Сообщения: 54
- Зарегистрирован: Пн авг 05, 2013 12:18:46
Re: Програмирование pic на СИ.
спасибо, ну да логично, то есть если я правильно понимаю когда нужно я задаю kbddelay или другой переменной нужное время а с каждым тиком они все дружно уменьшаются и мне остается ловить их обнуление и реагировать в соответствии с задачей?
-
spongebob
- Грызет канифоль
- Сообщения: 289
- Зарегистрирован: Пт мар 20, 2009 12:25:47
- Откуда: Ivanovo
- Контактная информация:
Re: Програмирование pic на СИ.
Доброго всем дня или ночи.
Вопрос такой. Как организовать побитовую работу с байтом на подобие структуры?
Например у меня есть байт (FLAGS) с флагами состояния программы. Есть функции для работы с битами (установить бит в 1, установить бит в 0, проверить состояние бита, инвертировать бит).
Каждый бит тоже имеет свое имя. Например:
#define WORK 0
#define MODE 1
И т.д.
Соответственно работа с каждым битом представляет собой вызов функции BitSet0 или другой с параметрами (байт, бит). Функции определены типа так:
#define BitSet1(reg, bit) reg |= (1<<bit)
А хочется простой доступ, с меньшей писаниной. Например FLAGS.WORK=1 и т.п.
Не будет ли реализация подобной хотелки требовать больше памяти и ресурсов и лучше оставить все как есть? А если нет, то как подобное раелизовать?
Спасибо!
Вопрос такой. Как организовать побитовую работу с байтом на подобие структуры?
Например у меня есть байт (FLAGS) с флагами состояния программы. Есть функции для работы с битами (установить бит в 1, установить бит в 0, проверить состояние бита, инвертировать бит).
Каждый бит тоже имеет свое имя. Например:
#define WORK 0
#define MODE 1
И т.д.
Соответственно работа с каждым битом представляет собой вызов функции BitSet0 или другой с параметрами (байт, бит). Функции определены типа так:
#define BitSet1(reg, bit) reg |= (1<<bit)
А хочется простой доступ, с меньшей писаниной. Например FLAGS.WORK=1 и т.п.
Не будет ли реализация подобной хотелки требовать больше памяти и ресурсов и лучше оставить все как есть? А если нет, то как подобное раелизовать?
Спасибо!
Re: Програмирование pic на СИ.
Ну так и пишите:
потом можно к ним обращаться
Насчет оптимальности - это к конкретному компилятору.
Код: Выделить всё
struct {
volatile unsigned char sec_event : 1;
volatile unsigned char adcready : 1;
} flag;Код: Выделить всё
if (flag.sec_event == 1) {
flag.sec_event = 0;-
spongebob
- Грызет канифоль
- Сообщения: 289
- Зарегистрирован: Пт мар 20, 2009 12:25:47
- Откуда: Ivanovo
- Контактная информация:
Re: Програмирование pic на СИ.
Это уже не бит в байте получается. И в случае чего в один байт того же еепром не влезет.
Re: Програмирование pic на СИ.
А что тогда????
вот это " :1" как раз и говорит, что тот чар сек_эвент занимает один бит. Более того, я таким образом обращаюсь к битам регистров, которые уж точно "один байт": INTCONbits.TMR0IF = 0; И этот INCONbits описан точно так же.
Re: Програмирование pic на СИ.
https://ru.wikipedia.org/wiki/%D0%91%D0 ... 0%BB%D0%B5spongebob писал(а):Это уже не бит в байте получается...
- Gray64
- Встал на лапы
- Сообщения: 96
- Зарегистрирован: Вт май 27, 2008 21:15:01
- Откуда: Украина
- Контактная информация:
Re: Програмирование pic на СИ.
Всем доброго дня.
Есть проблема. Ну это для меня проблема, а для знающих наверное не стоит выеденного яйца
.
Есть вот такой исходник:
#include <pic.h>
//Укажем слово конфигурации
__CONFIG (INTIO &WDTDIS &PWRTEN &MCLREN &BOREN &LVPDIS &UNPROTECT);
//Опишем переменные
const unsigned char step_table[4]={0b00010000,0b00100000,0b01000000,0b10000000};//Таблица состояний ключей
unsigned char cur_step;//Номер состояния в таблице
static void interrupt
isr(void){//Подпрограмма обработки прерываний
//Так как вектор прерывания у PIC16F628 общий, то функцию обработки внешнего прерывания
//начнём с проверки флага INTF, который устанавливается аппаратно при возникновении
//внешнего прерывания
if(INTF){//Если было внешнее прерывание
INTF = 0; //Сбрасываем флаг прерывания
if ((PORTB & 0b00000010) == 2){//Если нужно крутить по часовой, то
cur_step++;//увеличиваем указатель на элемент таблицы(массива)
if(cur_step == 4)cur_step = 0;//Если это последнее значение таблицы(массива), то идём в её начало
}
if((PORTB & 0b00000010) == 0){//Если нужно крутить против часовой, то
if(cur_step == 0) cur_step = 4;//Если текущее значение - это первое значение в таблице(в массиве), то идём в её конец
cur_step--;//уменьшаем указатель на элемент таблицы(массива)
}
}
}
void Init_CPU(void){//Настройка МК
CMCON = 0x07; //Отключаем встроенные компараторы
OPTION = 0b10000000 ;//Отключаем встроенные резисторы, внешнее прерывание INT - по спаду
TRISA = 0b11111111;//Весь порт А - на ввод
PORTB = 0x00; //Выводим в порт В нули
TRISB = 0x03; //Весь порт В кроме 2-х младших разрядов - на вывод
INTE = 1;//Разрешаем внешние прерывания
}
void main(void){//После сброса МК программа начнёт выполняться с этого места
Init_CPU();//Настроим МК
GIE = 1;//Глобальное разрешение прерываний
while(1){//Вечный цикл
PORTB = step_table[cur_step];//Выводим в порт значение из таблицы
};
}
В общем это "крутилка" для униполярнго шагового двигателя. Полное описание тут http://it-en.ru/cnc/doc/1.html Надо поменять табличку "шагов" для него. Так как я в Си полный ноль, для начала решил просто откомпилировать исходник, без всяких изменений, напартачить всегда успею. Создал проэкт в MPLAB, добавил исходник, но при компиляции выдаёт следующее:
Error [1091] C:\Program Files\HI-TECH Software\PICC\9.71a\sources\float.c; 86. main function "_main" not defined
Функция не определена. Что надо дописать-переписать?
Добавлено: Вопрос снят, всё ОК, накосячил при установке ПО...
Есть проблема. Ну это для меня проблема, а для знающих наверное не стоит выеденного яйца
Есть вот такой исходник:
Спойлер
//Добавим файл с описанием регистров МК#include <pic.h>
//Укажем слово конфигурации
__CONFIG (INTIO &WDTDIS &PWRTEN &MCLREN &BOREN &LVPDIS &UNPROTECT);
//Опишем переменные
const unsigned char step_table[4]={0b00010000,0b00100000,0b01000000,0b10000000};//Таблица состояний ключей
unsigned char cur_step;//Номер состояния в таблице
static void interrupt
isr(void){//Подпрограмма обработки прерываний
//Так как вектор прерывания у PIC16F628 общий, то функцию обработки внешнего прерывания
//начнём с проверки флага INTF, который устанавливается аппаратно при возникновении
//внешнего прерывания
if(INTF){//Если было внешнее прерывание
INTF = 0; //Сбрасываем флаг прерывания
if ((PORTB & 0b00000010) == 2){//Если нужно крутить по часовой, то
cur_step++;//увеличиваем указатель на элемент таблицы(массива)
if(cur_step == 4)cur_step = 0;//Если это последнее значение таблицы(массива), то идём в её начало
}
if((PORTB & 0b00000010) == 0){//Если нужно крутить против часовой, то
if(cur_step == 0) cur_step = 4;//Если текущее значение - это первое значение в таблице(в массиве), то идём в её конец
cur_step--;//уменьшаем указатель на элемент таблицы(массива)
}
}
}
void Init_CPU(void){//Настройка МК
CMCON = 0x07; //Отключаем встроенные компараторы
OPTION = 0b10000000 ;//Отключаем встроенные резисторы, внешнее прерывание INT - по спаду
TRISA = 0b11111111;//Весь порт А - на ввод
PORTB = 0x00; //Выводим в порт В нули
TRISB = 0x03; //Весь порт В кроме 2-х младших разрядов - на вывод
INTE = 1;//Разрешаем внешние прерывания
}
void main(void){//После сброса МК программа начнёт выполняться с этого места
Init_CPU();//Настроим МК
GIE = 1;//Глобальное разрешение прерываний
while(1){//Вечный цикл
PORTB = step_table[cur_step];//Выводим в порт значение из таблицы
};
}
Error [1091] C:\Program Files\HI-TECH Software\PICC\9.71a\sources\float.c; 86. main function "_main" not defined
Функция не определена. Что надо дописать-переписать?
Добавлено: Вопрос снят, всё ОК, накосячил при установке ПО...
Глаза боятся а руки делают!
Re: Програмирование pic на СИ.
Привет, Всем!
Не понимаю 1, почему не компилируется Си команда? В дизассемблере так выглядит
конкретнее команда count=0
Код: Выделить всё
148: if (count==2) {
142 0824 MOVF 0x24, W
143 3A02 XORLW 0x2
149: count=0;
150: } - Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Програмирование pic на СИ.
Она, скорее всего, компилируется. Просто в дизасемблере её не видно.
Попробуйте пошагать в режиме отладки и посмотрите, выполняется ли она.
Попробуйте пошагать в режиме отладки и посмотрите, выполняется ли она.
Re: Програмирование pic на СИ.
Подозреваю, что в строках 151, 152, 153 ... листинга и будет искомое. КМК в 142,143 - всего лишь _подготовка_ к сравнению.Alpout писал(а):Код: Выделить всё
148: if (count==2) { 142 0824 MOVF 0x24, W 143 3A02 XORLW 0x2 149: count=0; 150: }
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
Re: Програмирование pic на СИ.
Не не не ребята. Программа перешагивает команду!!! Эта команда внутри обработки прерывания, т.е.
Код: Выделить всё
128: void interrupt isr() {
004 00DE MOVWF 0x5e
005 0E03 SWAPF 0x3, W
006 1283 BCF 0x3, 0x5
007 00A0 MOVWF 0x20
008 080A MOVF 0xa, W
009 00A1 MOVWF 0x21
00A 292B GOTO 0x12b
129: unsigned char dig3, dig2, count;
130: dig3=0;
131: dig2=0;
12B 01A3 CLRF 0x23
132: if (T0IF) {
12C 1D0B BTFSS 0xb, 0x2
12D 2945 GOTO 0x145
133: PORTA&=0; //выключили аноды
12E 0185 CLRF 0x5
134: TMR0=0;
12F 0181 CLRF 0x1
135: if (count==0) {
130 08A4 MOVF 0x24, F
131 1D03 BTFSS 0x3, 0x2
132 2939 GOTO 0x139
136: PORTA=num[dig3][0];
133 083A MOVF 0x3a, W
134 0085 MOVWF 0x5
137: PORTC=num[dig3][1];
135 083B MOVF 0x3b, W
136 0087 MOVWF 0x7
138: RA0=1;
137 1405 BSF 0x5, 0
139: RA1=0;
138 1085 BCF 0x5, 0x1
140: }
141: if (count==1) {
139 0B24 DECFSZ 0x24, W
13A 2941 GOTO 0x141
142: PORTA=num[dig2][0];
13B 083A MOVF 0x3a, W
13C 0085 MOVWF 0x5
143: PORTC=num[dig2][1];
13D 083B MOVF 0x3b, W
13E 0087 MOVWF 0x7
144: RA0=0;
13F 1005 BCF 0x5, 0
145: RA1=1;
140 1485 BSF 0x5, 0x1
146: }
147: count++;
141 0AA4 INCF 0x24, F
148: if (count==2) {
142 0824 MOVF 0x24, W
143 3A02 XORLW 0x2
149: count=0;
150: }
151: T0IF = 0;
144 110B BCF 0xb, 0x2
152: }
153: }
145 0821 MOVF 0x21, WRe: Програмирование pic на СИ.
У вас эта переменная динамическая. Компилятор её соптимизировал? Потому как по выходу из прерывания она уничтожается, так нафига её обнулять?
p.s. Поставили бы повыше уровень оптимизации и сравнение тоже исчезло бы...
p.s. Поставили бы повыше уровень оптимизации и сравнение тоже исчезло бы...


