Програмирование pic на СИ.
Re: Програмирование pic на СИ.
NStorm, спасибо. Дизасму включил. Камень pic10f322, это я реализовал контроллер управления питанием от Li-ion, который включает/выключает нагрузку от нажатия кнопки на 15 минут (с автоотключением), или без автоотключения в зависимости от положения перемычки. Так же идет предупреждение звуковым сигналом, если напряжение на АКБ меньше 3,2В, или отключение при напряжении на АКБ менее 3В.
По поводу:
1. Так как это контроллер управления питанием, то он всегда подключен к банке АКБ, поэтому единоразовая проверка(во время инициализации регистров) не подходит поэтому проверка в коде программы, и режимы работы легко меняются в активном состоянии. Хотя раньше я делал в ассемблере, как Вы советуете.
2. А как кнопка может тормознуть программу? Опрос кнопки идет на определенном участке программы, а прерывания отключены в основном цикле программы, и вкл только на период сна
3. Так с конца программы после звукового сигнала отключения итак идет переход на начало (после Power_Off) на while (1) и контроллер уходит в спячку.
Насчет безGOTOвых переходов еще потренируюсь писать программы, чтобы обойтись без них.
По поводу:
1. Так как это контроллер управления питанием, то он всегда подключен к банке АКБ, поэтому единоразовая проверка(во время инициализации регистров) не подходит поэтому проверка в коде программы, и режимы работы легко меняются в активном состоянии. Хотя раньше я делал в ассемблере, как Вы советуете.
2. А как кнопка может тормознуть программу? Опрос кнопки идет на определенном участке программы, а прерывания отключены в основном цикле программы, и вкл только на период сна
3. Так с конца программы после звукового сигнала отключения итак идет переход на начало (после Power_Off) на while (1) и контроллер уходит в спячку.
Насчет безGOTOвых переходов еще потренируюсь писать программы, чтобы обойтись без них.
Re: Програмирование pic на СИ.
2. Ну вас в коде одна проверка: "if (!TK) // если кнопка нажата - подаем короткий звуковой сигнал" внутри сразу уже в любом случае происходит сигнал, после которого ожидание 999мс. Вот тут и тормозится.
3. return в c - выход из функции. Из main() значит завершение программы. Не уверен, как код генерит xc8, но в avr-gcc насколько я помню в этом случае проиходит переход ко встроенной функции exit(), где просто крутится бесконечный цикл. Надо будет глянуть что xc8 выдает при return'e из main().
3. return в c - выход из функции. Из main() значит завершение программы. Не уверен, как код генерит xc8, но в avr-gcc насколько я помню в этом случае проиходит переход ко встроенной функции exit(), где просто крутится бесконечный цикл. Надо будет глянуть что xc8 выдает при return'e из main().
Re: Програмирование pic на СИ.
3. Глянул в дизасм, там нормальный переход GOTO 0x12B на начало программы, после чего сон)
2. Точно, 2 проверки состояния кнопки. Короткое нажатие просто сбрасывает таймер ожидания и подает звуковой сигнал (чтобы устройство не отключилось). Длинное нажатие более 1 сек подает сначала короткий звуковой сигнал, а потом двухтональный сигнал отключения и спячка
Код: Выделить всё
143: PWM1EN = 0; // выкл ШИМ
01F6 1396 BCF PWM1CON, 0x7
144: LED = 0; // отключаем питание
01F7 1105 BCF PORTA, 0x2
01F8 292B GOTO 0x12B
145: }
146: return;
147:
148: }Re: Програмирование pic на СИ.
Глянул выхлоп xc8 - понятно, он инициализацию пихает в конец, а return из main() реально возвращается в конец инициализации этой, на последней адрес во флэш памяти. Тем самым прокручивая PC обратно до 0. Но как-то это неправильно с точки зрения Си. Это не на while(1) прыжок обратно, а всей программы сначала. Все переменные будут переинициализированы.
Кстати полный дизасм еще генерится в каталоге с проектом в подкаталоге dist/default/TARGET/PROJECT.lst
Кстати полный дизасм еще генерится в каталоге с проектом в подкаталоге dist/default/TARGET/PROJECT.lst
Re: Програмирование pic на СИ.
Да нет, именно на while(1) прыгает.
Код: Выделить всё
47: while (1)
48: {
49: PWM1CON = 0b00000000; // отключаем ШИМ1
012B 0196 CLRF PWM1CON
50: FVRCON = 0b00000000; // отключаем ИОН, отключаем температурный индикатор
012C 019D CLRF FVRCONRe: Програмирование pic на СИ.
3. В общем всё-равно на МК в общем принципе для портабельности лучше избегать return из main().
2. Ну если вам тут не важно, что нажатие кнопки даже короткое по сути откладывает измерение АЦП на секунду, то можно и так конечно оставить.
2. Ну если вам тут не важно, что нажатие кнопки даже короткое по сути откладывает измерение АЦП на секунду, то можно и так конечно оставить.
Это видимо оптимизатор постарался. Вообще в целом return из main() в embedded зависит от компилятора.Да нет, именно на while(1) прыгает.
Re: Програмирование pic на СИ.
Вообщем СИ и МПЛАБ Х вещь, раньше сидел на Асме, и не знаю сколько бы у меня ушло времени на написание аналогичной программы, где куча программных таймеров связанных между собой. А вышеуказанную программу написал менее чем за день с учетом того, что раньше не имел опыта написания программ на СИ (мигание светодиода не в счет).
Еще конфигурируемые логические ячейки довольно забавная вещь. https://habr.com/ru/post/372509/ Я проверил - работает, но правда ног у 10f322 очень мало. Закажу МК, где ног побольше для экспериментов. Можно будет например аппаратные подавители дребезга контактов кнопки/энкодера делать...
Еще конфигурируемые логические ячейки довольно забавная вещь. https://habr.com/ru/post/372509/ Я проверил - работает, но правда ног у 10f322 очень мало. Закажу МК, где ног побольше для экспериментов. Можно будет например аппаратные подавители дребезга контактов кнопки/энкодера делать...
Re: Програмирование pic на СИ.
4uvak, всё-таки это не программные таймеры, а просто задержки. Но в остальном вы правы, на Си куда проще многие штуки делаются. Но надо учиться абстрагироваться от асма, тут так в лоб не надо. Я даже не о сложных абстракциях, которые можно делать в Си, а просто хотя бы к базовым вещами привакать - не надо "переходить", надо вызывать функции. А потом еще привыкаем к тому, что у функций бывают аргументы и возвращаемое значение.
- КРАМ
- Друг Кота
- Сообщения: 25141
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Програмирование pic на СИ.
[uquote="NStorm",url="/forum/viewtopic.php?p=3909698#p3909698"]у функций бывают аргументы и возвращаемое значение.[/uquote]
Прямого отношения к Си это не имеет. На АСМе совершенно так же делаются вызовы, в подпрограмму передаются значения и подпрограмма возвращает значение.
Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык.
Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.
Прямого отношения к Си это не имеет. На АСМе совершенно так же делаются вызовы, в подпрограмму передаются значения и подпрограмма возвращает значение.
Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык.
Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.
Re: Програмирование pic на СИ.
[uquote="КРАМ",url="/forum/viewtopic.php?p=3909720#p3909720"]Прямого отношения к Си это не имеет. На АСМе совершенно так же делаются вызовы, в подпрограмму передаются значения и подпрограмма возвращает значение.
Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык.[/uquote]
Без сомнения. Но обычно на асме более прямолинейно всегда пишут. ЯВУ всё-таки более располагает к большему уровню абстракции
[uquote="КРАМ",url="/forum/viewtopic.php?p=3909720#p3909720"]Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.[/uquote]
Смотря какой уровень сложности программы и владения ЯВУ. Структуры в Си, например, очень сильно могу сократить объем и наглядность кода. Да и портабельность с ЯВУ проще - перейти с одной архитектуры на другую с ЯВУ попроще - не надо набор инструкций на низком уровне изучать и "привыкать" к ним. Но я не хочу разводить холивар на этом месте. Везде свои преимущества. Оптимизация под архитектуру на асме ес-но возможна такая, которой ни один оптимизатор ЯВУ не сможет.
Тут дело не в языке, а в мышлении. В способности генерировать абстракции вообще, а не потому, что так требует язык.[/uquote]
Без сомнения. Но обычно на асме более прямолинейно всегда пишут. ЯВУ всё-таки более располагает к большему уровню абстракции
[uquote="КРАМ",url="/forum/viewtopic.php?p=3909720#p3909720"]Кстати, код написанный на АСМе в стиле языка высокого уровня не намного более объёмен нежели в ЯВУ.[/uquote]
Смотря какой уровень сложности программы и владения ЯВУ. Структуры в Си, например, очень сильно могу сократить объем и наглядность кода. Да и портабельность с ЯВУ проще - перейти с одной архитектуры на другую с ЯВУ попроще - не надо набор инструкций на низком уровне изучать и "привыкать" к ним. Но я не хочу разводить холивар на этом месте. Везде свои преимущества. Оптимизация под архитектуру на асме ес-но возможна такая, которой ни один оптимизатор ЯВУ не сможет.
Re: Програмирование pic на СИ.
Подскажите как начать цикл заново не используя команду перехода по меткам GOTO? Компилятор XC8
- КРАМ
- Друг Кота
- Сообщения: 25141
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Програмирование pic на СИ.
[uquote="4uvak",url="/forum/viewtopic.php?p=3910220#p3910220"]Подскажите как[/uquote]
Вы лучше сформулируйте задачу.
Вместо goto нужно оформить цикл while с условием или без него - бесконечный цикл:
Вы лучше сформулируйте задачу.
Вместо goto нужно оформить цикл while с условием или без него - бесконечный цикл:
Код: Выделить всё
while(1) {
// тут содержимое цикла
}Re: Програмирование pic на СИ.
Это начало основного цикла while (1), по условиям ложного срабатывания (контроллер чувствителен к помехам по цепям питания) и он ложно может выйти из сна через прерывание. Поэтому я добавил строку с проверкой срабатывания кнопки после сна. Если кнопка не нажата нужно повторно отправиться спать. Я организовал команду перехода через goto qwe. Есть другой способ начать цикл заново?
Код: Выделить всё
while (1)
{
qwe:
PWM1CON = 0b00000000; // отключаем ШИМ1
FVRCON = 0b00000000; // отключаем ИОН, отключаем температурный индикатор
ADCON = 0b00000000; // отключаем модуль АЦП
PORTA = 0; // все выходы порта переводим в низкое состояние
__delay_ms(500);
IOCIE = 1; // разрешаем прерывание по изменению уровня PORTA
IOCAF = 0; // сбрасываем флаг IOCAF (свидетельствующий о прерывании RA3)
SWDTEN = 0; // отключаем сторожевой таймер на период сна
SLEEP(); // здоровый крепкий сон до пробуждения нажатием кнопки)
IOCIE = 0; // запрет прерывания по изменению уровня PORTA
SWDTEN = 1; // включаем сторожевой таймер
__delay_ms(50);
if (TK) // если кнопка отжата - было ложное страбатывание прерывания (из-за помех по цепям питания), отправляемся повторно спать
{
goto qwe;
}
CLRWDT();
LED = 1; // включаем питание- КРАМ
- Друг Кота
- Сообщения: 25141
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Програмирование pic на СИ.
Тогда так:
Код: Выделить всё
while(1){
// тут какой то код перед началом ожидания кнопки
while(условие не нажатой кнопки){
// тут код пока кнопка не нажата
}
// тут код после нажатой кнопки
}
Re: Програмирование pic на СИ.
4uvak, я вам дал на прошлой странице пример с функциями. Просто вынесите выключение и сон в отдельную функцию и вызывайте её в данном случае. А после неё можно как у вас сделать return (уже из main()), чтобы "перезапуститься".
Еще лучше - начинать переходить к конечному автомату. Если писать сразу так, то все эти переходы между состояниями легче расширяются и обрабатываются.
Вот простенький относительно пример: https://github.com/N-Storm/flashlight/b ... ashlight.c
Это я делал для фонарика прошивку на замен штатному китайскому МК на базе PIC10F200 - самый простой и примитивный МК пожалуй в мире из ныне выпускающихся. У него нет прерываний. Поэтому с некоторыми вещами пришлось "извращаться" и очень мало памяти, чтобы сделать красивее. Но оно работает. ) Вот выключение сделано в функции enter_sleep(), которая всё выключает и отправляет МК в сон, как вам нужно.
С нажатием кнопки тоже посмотрите как сделано. Точно также лучше просто в основном цикле если нажата кнопка - увеличиваем некую переменную счетчик. А если отжата - проверяем значение счетчика и тут понятно что у нас было - короткое нажатие, длинное или просто дребезг.
Но если хотите "простыней", то что мешает вместо if (TK) goto qwe; написать:
Еще лучше - начинать переходить к конечному автомату. Если писать сразу так, то все эти переходы между состояниями легче расширяются и обрабатываются.
Вот простенький относительно пример: https://github.com/N-Storm/flashlight/b ... ashlight.c
Это я делал для фонарика прошивку на замен штатному китайскому МК на базе PIC10F200 - самый простой и примитивный МК пожалуй в мире из ныне выпускающихся. У него нет прерываний. Поэтому с некоторыми вещами пришлось "извращаться" и очень мало памяти, чтобы сделать красивее. Но оно работает. ) Вот выключение сделано в функции enter_sleep(), которая всё выключает и отправляет МК в сон, как вам нужно.
С нажатием кнопки тоже посмотрите как сделано. Точно также лучше просто в основном цикле если нажата кнопка - увеличиваем некую переменную счетчик. А если отжата - проверяем значение счетчика и тут понятно что у нас было - короткое нажатие, длинное или просто дребезг.
Но если хотите "простыней", то что мешает вместо if (TK) goto qwe; написать:
Код: Выделить всё
IOCIE = 0; // запрет прерывания по изменению уровня PORTA
SWDTEN = 1; // включаем сторожевой таймер
__delay_ms(50);
if (!TK) // если кнопка нажата
{
CLRWDT();
LED = 1; // включаем питание
...
}
// qwe:
...
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Програмирование pic на СИ.
оператор continue немедленно осуществляет переход к проверке условия продолжения цикла (внутри которого находится этот оператор) - это 100% то самое, что вам нужно для замены goto
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Програмирование pic на СИ.
Всем добрый день, я в программировании не понимаю, нужна прошивка для pic12f675 или pic12f629 для датчика скорости одометра вектра б, в мплаб пробовал компилировать исходники и постоянно выбрасывает ошибки, прошу вашей помощи.
- Вложения
-
- main.c
- (3.96 КБ) 317 скачиваний
Re: Програмирование pic на СИ.
igorua27, какой у вас компилятор, какая версия mplab?
Добавлено after 1 minute 2 seconds:
Вангую, что у вас стоит XC8. А прошивка написана под HI-TECH PICC.
Добавлено after 1 minute 2 seconds:
Вангую, что у вас стоит XC8. А прошивка написана под HI-TECH PICC.
Re: Програмирование pic на СИ.
mplab x ide v5.45 компилятор XC8. А как переписать под XC8? Что нужно изменить?
Re: Програмирование pic на СИ.
igorua27, а под XC8 она не соберется, т.к. в бесплатной версии плохая оптимизация и по месту из-за float операций не влезет. Если найдете PRO версию, то вот так переделать:
Вам частоту импульсов нужно умножить на некий коэф? Какой будет коэф у вас ?
Спойлер
Код: Выделить всё
/****************************************************************/
/* Множитель/делитель частоты */
/* http://radiokot.ru/forum/viewtopic.php?f=20&t=59172 */
/* */
/* МК: PIC12F675 */
/* */
/* Автор: Alex */
/* al.kl@list.ru */
/* http://ChipMk.ru */
/****************************************************************/
// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#include <xc.h>
#include <stdbool.h> /* For true/false definition */
#include <pic12f675.h>
#define _XTAL_FREQ 4000000 // 4 MHz INTOSC
//static volatile near unsigned int TMR1 @ 0x00E;
/****************************************************************/
#define MUL 1.5 // Множитель
#define PIN_OUT GPIO0 // Выходной ПИН
#define TRIS_OUT TRISIO0 //
/****************************************************************/
volatile unsigned long Per_In = 0; // Преобразованный период входного сигнала
static bool In_Fl = 0; // Флаг окончания преобразования периода
volatile unsigned long Per_Out = 0; // Период выходного сигнала
/****************************************************************/
/****************************************************************/
/****************************************************************/
void main() {
CMCON = 7; // Настраиваем порты как цифровые
ANS0 = 0; //
ANS1 = 0; //
ANS2 = 0; //
ANS3 = 0; //
TRIS_OUT = 0;
PIN_OUT = 0;
T0CS = 0;
PSA = 1;
PS2 = 0;
PS1 = 0;
PS0 = 0;
TMR0 = 0;
T0IE = 1;
TMR1ON = 1;
TMR1IE = 0;
INTE = 1;
INTEDG = 0;
PEIE = 1;
GIE = 1;
Per_Out = 0;
while (1) {
unsigned long per_tmp;
if (In_Fl) {
In_Fl = 0;
//--------------------
GIE = 0;
per_tmp = Per_In;
GIE = 1;
per_tmp /= 2;
//--------------------
if (per_tmp) {
per_tmp = (unsigned long)(per_tmp / MUL);
GIE = 0;
Per_Out = per_tmp;
GIE = 1;
TMR1IE = 1;
} else {
TMR1IE = 0;
PIN_OUT = 0;
}
}
}
}
/****************************************************************/
void interrupt isr() {
static bool p_fl = 0; // Флаг преобразования входного периода
static unsigned int H_Per_In = 0; // Старшие байты вх. периода
static unsigned char H_Per_Out = 0; // Старший байт вых. периода
//-------------------------------------//
if (INTF) {
INTF = 0;
if (!p_fl) {
p_fl = 1;
TMR0 = 0;
H_Per_In = 0;
} else {
*((char*) &Per_In) = TMR0 + 5;
TMR0 = 0;
if (T0IF) // Если было переполнение
H_Per_In++; // обрабатываем его
*((int*) ((char*) &Per_In + 1)) = H_Per_In;
H_Per_In = 0;
In_Fl = 1; // Ставим флаг окончания преобразования
}
T0IF = 0;
}
//-------------------------------------//
if (T0IF && T0IE) {
T0IF = 0;
H_Per_In++; // +256
if (*((char*) &H_Per_In + 1) >= 16) { // >=16*65536 ~1000000 МЦ
H_Per_In = 0;
p_fl = 0; // Сброс флага преобразования
Per_In = 0; // Период = 0
In_Fl = 1; // Ставим флаг окончания преобразования
}
}
//-------------------------------------//
if (TMR1IF && TMR1IE) {
TMR1IF = 0;
if (!H_Per_Out--) {
TMR1 -= *((int*) ((char*) &Per_Out));
H_Per_Out = *((char*) &Per_Out + 2);
PIN_OUT = !PIN_OUT;
}
}
//-------------------------------------//
}