Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить

Re: Програмирование pic на СИ.

Пт дек 13, 2024 23:02:10

У меня компилятор XC8 v 1.41 не распознает STATUS_bits.C = 0; не распознает. :(
Смотрите как прописаны биты регистра STATUS в заголовочном файле XC8 для вашего микроконтроллера. У меня эти файлы в по такому пути расположены: C:\Program Files\Microchip\xc8\v1.33\include

Re: Програмирование pic на СИ.

Пт дек 13, 2024 23:39:04

Вот так. Только подсказал бы как этим пользоваться.
// Register: STATUS
extern volatile unsigned char STATUS @ 0x003;
#ifndef _LIB_BUILD
asm("STATUS equ 03h");
#endif
// bitfield definitions
typedef union {
struct {
unsigned C :1;
unsigned DC :1;
unsigned Z :1;
unsigned nPD :1;
unsigned nTO :1;
unsigned RP :2;
unsigned IRP :1;
};
struct {
unsigned :5;
unsigned RP0 :1;
unsigned RP1 :1;
};
struct {
unsigned CARRY :1;
unsigned :1;
unsigned ZERO :1;
};
} STATUSbits_t;
extern volatile STATUSbits_t STATUSbits @ 0x003;
// bitfield macros
#define _STATUS_C_POSN 0x0
#define _STATUS_C_POSITION 0x0
#define _STATUS_C_SIZE 0x1
#define _STATUS_C_LENGTH 0x1
#define _STATUS_C_MASK 0x1
#define _STATUS_DC_POSN 0x1
#define _STATUS_DC_POSITION 0x1
#define _STATUS_DC_SIZE 0x1
#define _STATUS_DC_LENGTH 0x1
#define _STATUS_DC_MASK 0x2
#define _STATUS_Z_POSN 0x2
#define _STATUS_Z_POSITION 0x2
#define _STATUS_Z_SIZE 0x1
#define _STATUS_Z_LENGTH 0x1
#define _STATUS_Z_MASK 0x4
#define _STATUS_nPD_POSN 0x3
#define _STATUS_nPD_POSITION 0x3
#define _STATUS_nPD_SIZE 0x1
#define _STATUS_nPD_LENGTH 0x1
#define _STATUS_nPD_MASK 0x8
#define _STATUS_nTO_POSN 0x4
#define _STATUS_nTO_POSITION 0x4
#define _STATUS_nTO_SIZE 0x1
#define _STATUS_nTO_LENGTH 0x1
#define _STATUS_nTO_MASK 0x10
#define _STATUS_RP_POSN 0x5
#define _STATUS_RP_POSITION 0x5
#define _STATUS_RP_SIZE 0x2
#define _STATUS_RP_LENGTH 0x2
#define _STATUS_RP_MASK 0x60
#define _STATUS_IRP_POSN 0x7
#define _STATUS_IRP_POSITION 0x7
#define _STATUS_IRP_SIZE 0x1
#define _STATUS_IRP_LENGTH 0x1
#define _STATUS_IRP_MASK 0x80
#define _STATUS_RP0_POSN 0x5
#define _STATUS_RP0_POSITION 0x5
#define _STATUS_RP0_SIZE 0x1
#define _STATUS_RP0_LENGTH 0x1
#define _STATUS_RP0_MASK 0x20
#define _STATUS_RP1_POSN 0x6
#define _STATUS_RP1_POSITION 0x6
#define _STATUS_RP1_SIZE 0x1
#define _STATUS_RP1_LENGTH 0x1
#define _STATUS_RP1_MASK 0x40
#define _STATUS_CARRY_POSN 0x0
#define _STATUS_CARRY_POSITION 0x0
#define _STATUS_CARRY_SIZE 0x1
#define _STATUS_CARRY_LENGTH 0x1
#define _STATUS_CARRY_MASK 0x1
#define _STATUS_ZERO_POSN 0x2
#define _STATUS_ZERO_POSITION 0x2
#define _STATUS_ZERO_SIZE 0x1
#define _STATUS_ZERO_LENGTH 0x1
#define _STATUS_ZERO_MASK 0x4

Re: Програмирование pic на СИ.

Пт дек 13, 2024 23:46:52

У меня ...

нет там нижнего подчеркивания
но дело даже не в этом - в си не надо проверять флаг переноса и пытаться "btfsc" выполнить ... это ж не асм
тоже самое и с "goto" - не нужен в си безусловный переход

Re: Програмирование pic на СИ.

Пт дек 13, 2024 23:52:28

У меня ...

нет там нижнего подчеркивания
но дело даже не в этом - в си не надо проверять флаг переноса и пытаться "btfsc" выполнить ... это ж не асм
тоже самое и с "goto" - не нужен в си безусловный переход

Вы меня в каждой теме "поражаете". Что не вопрос то хвастовство, что всё знаете. Знаете? Хорошо, отлично. Считаете, что я не достоин Вашего совета и подсказки? Проходите мимо. То, что Вы пишете - об этом весь интернет кишит. К сожалению нет полноценного обучения данной теме. Приходится самому карабкаться. Можете подсказать? Подскажите как. Не хотите - мимо.

Re: Програмирование pic на СИ.

Сб дек 14, 2024 00:12:19

В какой ещё "каждой"? Вы меня с кем-то путаете... Я точно также как и вы сравнительно недавно начал осваивать си...
То, что я написал - это и есть подсказки. Могу повторить - не проверяйте флаг С. Найдите другой способ. Вы же его проверять зачем хотите? Чтобы перенос отследить, верно? После чего? Вычитания? Ну так есть же операторы больше/меньше - используйте их. Я к тому, что например, зачем отнимать 5 из 3, если 3 меньше пяти... и это можно выяснить ещё до вычитания ... как вариант ...

насчет ещё флага С - его можно использовать в иных (своих) целях ... например, в функции записи в ипром, прежде чем отключить прерывания, им временно можно запомнить текущее состояние GIE :
STATUSbits.CARRY = 0;
if (INTCONbits.GIE) {STATUSbits.CARRY = 1;}
INTCONbits.GIE = 0;
чтобы потом именно восстановить как было, а не тупо включить
if (STATUSbits.CARRY) {INTCONbits.GIE = 1;}
разумеется, это для случаев, когда в промежутке точно нет кода. который может повлиять на него (сдвиги, арифметика) ... а здесь как раз такой случай, ибо речь о последовательности раблокировки записи

Re: Програмирование pic на СИ.

Сб дек 14, 2024 00:18:41

Спасибо за открытый ответ. Буду курить информацию.

Re: Програмирование pic на СИ.

Пн дек 16, 2024 14:56:52

Друзья. Объясните, пожалуйста, как быть с регистром W. Как его в Си сохранять в прерываниях и вообще работать с ним. И еще. В MPLAB он весит по адресу 0x9F но там же висит и ADCON1. Как так? Заранее спасибо за ответ.

Re: Програмирование pic на СИ.

Пн дек 16, 2024 15:31:27

Друзья. Объясните, пожалуйста, как быть с регистром W.

Никак не быть. Вам уже объяснили, что в Си нельзя применять то, что Си использует для своих целей.
Нельзя писать на Си, копируя код на АСМе. Поэтому забудьте про названия регистров ядра. В Си это табу. Можно использовать только ОЗУ, флеш и регистры периферии. Но тоже по правилам Си.
Как так?

В младших пиках ОЗУ разделено на банки. Обращение в дизасме к определенному адресу ничего не означает. Для того, чтобы узнать в какой банк произошло обращение, нужно смотреть на RP-биты регистра STATUS. Если вы пишите на Си, забудьте об этом. Это вас не касается. Компилятор все сделает как надо.

Re: Програмирование pic на СИ.

Ср дек 18, 2024 14:43:41

Товарищи! Правильно ли я делаю подключение функции из другого файла? Есть функция предположим - void fun_1(void) в файле. Я пытаюсь вызвать её в main следующим способом:

extern void fun_1(void);
void main (void)
{
extern fun_1(void);
return;
}
Но ничего не выходит. Компилятор говорит - "На текущем компьютере не найдено ни одной строки исходного кода"
Подскажите, пожалуйста с extern. Заранее спасибо.

Добавлено after 7 minutes 33 seconds:
Товарищи! Я ПОНЯЛ!!! Невнимательность моя! ):

extern void fun_1(void);
void main (void)
{
fun_1();
return;
}

Re: Програмирование pic на СИ.

Ср дек 18, 2024 22:09:48

А причем тут extern?
Для функций объявленных в другом файле или даже в этом, но ниже ее вызова, объявляют ее прототип в начале кода.
А экстерном объявляют переменные используемые в этом файле, но объявленные в другом, чтобы не было повторного объявления..

Re: Програмирование pic на СИ.

Чт дек 19, 2024 12:28:48

А причем тут extern?

При том, что функции определённые в других модулях являются внешними, хотя extern в прототипе указывать не обязательно.

Re: Програмирование pic на СИ.

Чт дек 19, 2024 14:00:30

При том, что функции определённые в других модулях являются внешними

Внезапно все функции в Си по умолчанию получают спецификатор extern (в отличии от static).
Поэтому писать его в прототипе нет никакой необходимости - он будет проигнорирован.

Re: Програмирование pic на СИ.

Пн дек 23, 2024 16:11:49

Друзья, а можно ли в MPLAB разбивать ассемблерный файл как в си, по разным файлам? К примеру - в одном файле основная программа, а прерывания в другом файле? Если да то как это реализовать? Заранее спасибо.

Re: Програмирование pic на СИ.

Пн дек 23, 2024 20:53:45

создаем новый файл в папке проекта (скажем - int.asm) ... в нем пишем код ... затем там, где этот код должен размещаться пишем INCLUDE "int"
Либо изначально создаем некий главный файл (main.asm) и в нем уже определяем карту всего кода, типа так:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0x00
goto _INIT

org 0x04
INCLUDE "int"
INCLUDE "INIT"
INCLUDE "FILE1"
INCLUDE "FILE2"
;
;
org 0x700
INCLUDE "TABLE"
;
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Чередуем, убираем, добавляем, фиксируем по нужным адресам .... как душе угодно
метка _INIT в файле INIT.asm

Re: Програмирование pic на СИ.

Пн дек 23, 2024 21:59:34

Спасибо Вам огромное.

Re: Програмирование pic на СИ.

Пт апр 11, 2025 10:04:47

Всем доброго дня. Подскажите пожалуйста как в MPLAB назначить переменной определенный адрес? Я пытаюсь сделать так:

uint8_t *Var_70 = 0x70; // Пытаюсь привязать адрес указателем

if (isBitSet(&Var_70,1)){ //Вызываю в функции из регистра
Func_27B();
Не компилируется. Что не так я делаю?
Заранее спасибо за помощь.

Re: Програмирование pic на СИ.

Пт апр 11, 2025 12:58:08

Я сейчас точно не помню как реализован синтаксис абсолютного адреса конкретно в XC8 и XC16, но общее правило - это спецификатор at или @ в объявлении переменной.
uint8_t var __at(0x1000);

Re: Програмирование pic на СИ.

Пт апр 11, 2025 13:27:37

Я сейчас точно не помню как реализован синтаксис абсолютного адреса конкретно в XC8 и XC16, но общее правило - это спецификатор at или @ в объявлении переменной.
uint8_t var __at(0x1000);

Спасибо большое!!! uint8_t Var_70 __at(0x70); ПРОКАТИЛО!!! XC8

Re: Програмирование pic на СИ.

Чт май 22, 2025 10:01:07

Привет. Я пытаюсь изучить программирование PIC на си.
Сочинил в mplab x простую программу под xc8 v2.50
Программа работает только на половину.
Задумка была такая. Брать из массива число по индексу массива
и отправлять это число в порт. Индикация светодиодами для контроля.
Управление от двух кнопок.
Получилось, что та часть программы, которая считает переменную - индекс массива
в плюс, работает корректно, а та часть, где индекс должен уменьшаться,
просто пролетает до нуля от первого нажатия на кнопку.
При этом декремент на самом деле происходит, но не на единицу, как должно быть,
а сразу уменьшает до нуля, как будто в цикле for. С инкрементом ни каких проблем.
Проверял и в протеусе 8.17, и на реальном макете.
Пошаговая отладка в mplab x проходит правильно.
Не работает, как задумывалось, а что упустил, не пойму.
Светодиодом мигал.

Спойлер
Код:
/*
 * File:   main.c
 * Mplab X v5.35
 * XC8 compiler v2.50
 * For Proteus v8.17
 */

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>

#define _XTAL_FREQ 2000000 // 2Mhz xtal

unsigned char array[] = { //Data to port C
 0xA5,0x5A,0xF0,0x0F
};

volatile unsigned char flag_up = 0;
volatile unsigned char flag_dn = 0;
volatile unsigned char counter = 0;

unsigned char CheckButton(void) {
        if(RB4 == 0) {                // If button press
           __delay_ms(15);          // Anti-bounce protect
                if (RB4 == 0) {
                flag_up = 1;                 // Enable flag
           } else {
                    return  flag_up;
           }
        }
        if(RB1 == 0) {
           __delay_ms(15);
               if (RB1 == 0) {
                flag_dn = 1;                // Enable flag
           } else {
                    return  flag_dn;
           }
        }
      return flag_up, flag_dn; 
}

unsigned char CountArray (void) {
    unsigned char i = counter;
   if(CheckButton()) {
        if(flag_up == 1) {
            flag_up = 0;
            if(counter != 4){
            (counter)++;
            }
        }
        if(flag_dn == 1) {
            flag_dn = 0;
            if(counter != 0){
            (counter)--;
            }
        }
   }
   return i;
}

void main(void) {
  TRISC = 0x00;                      // Dir. for PORTC
  PORTC = 0x00;                     // Data output port
  TRISB = 0b00010010;           // Dir. for PORTB, button input thr. RB4 and RB1
  PORTB = 0x00;
  while(1) {
      if(CountArray()) {
           PORTC=array[counter]; // Write data to PORTC
             __delay_ms(100);
      }
  }
  return;
}


Это код, который не работает.

СпойлерИзображение


Схема под этот код.

I need help. :cry:

Re: Програмирование pic на СИ.

Чт май 22, 2025 10:48:00

Не вникал в логику, но строчка
Код:
return flag_up, flag_dn;
по сути эквивалентна
Код:
return flag_dn;
Так как return возвращает одно значение. А оператор , просто выполняет выражения по порядку и возвращает последнее.

Если надо иметь на выходе функции единицу, если хоть один флаг выставлен, то используйте или лог.ИЛИ или даже побитное ИЛИ.
Код:
return flag_up | flag_dn;
Ответить