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

Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Serg290",url="/forum/viewtopic.php?p=4661041#p4661041"]Друзья. Объясните, пожалуйста, как быть с регистром W.[/uquote]
Никак не быть. Вам уже объяснили, что в Си нельзя применять то, что Си использует для своих целей.
Нельзя писать на Си, копируя код на АСМе. Поэтому забудьте про названия регистров ядра. В Си это табу. Можно использовать только ОЗУ, флеш и регистры периферии. Но тоже по правилам Си.
[uquote="Serg290",url="/forum/viewtopic.php?p=4661041#p4661041"]Как так?[/uquote]
В младших пиках ОЗУ разделено на банки. Обращение в дизасме к определенному адресу ничего не означает. Для того, чтобы узнать в какой банк произошло обращение, нужно смотреть на RP-биты регистра STATUS. Если вы пишите на Си, забудьте об этом. Это вас не касается. Компилятор все сделает как надо.
Реклама
Открыл глаза
Сообщения: 57
Зарегистрирован: Пн апр 08, 2019 11:03:59

Сообщение Serg290 »

Товарищи! Правильно ли я делаю подключение функции из другого файла? Есть функция предположим - 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;
}
Реклама
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

А причем тут extern?
Для функций объявленных в другом файле или даже в этом, но ниже ее вызова, объявляют ее прототип в начале кода.
А экстерном объявляют переменные используемые в этом файле, но объявленные в другом, чтобы не было повторного объявления..
OKF
Это не хвост, это антенна
Сообщения: 1407
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4661865#p4661865"]А причем тут extern?[/uquote]
При том, что функции определённые в других модулях являются внешними, хотя extern в прототипе указывать не обязательно.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="OKF",url="/forum/viewtopic.php?p=4661971#p4661971"]При том, что функции определённые в других модулях являются внешними[/uquote]
Внезапно все функции в Си по умолчанию получают спецификатор extern (в отличии от static).
Поэтому писать его в прототипе нет никакой необходимости - он будет проигнорирован.
Реклама
Открыл глаза
Сообщения: 57
Зарегистрирован: Пн апр 08, 2019 11:03:59

Сообщение Serg290 »

Друзья, а можно ли в MPLAB разбивать ассемблерный файл как в си, по разным файлам? К примеру - в одном файле основная программа, а прерывания в другом файле? Если да то как это реализовать? Заранее спасибо.
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 162
Зарегистрирован: Чт ноя 26, 2015 23:22:35
Откуда: не с Уфы

Сообщение Родэрик »

создаем новый файл в папке проекта (скажем - 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
Контактная информация:
Открыл глаза
Сообщения: 57
Зарегистрирован: Пн апр 08, 2019 11:03:59

Сообщение Serg290 »

Спасибо Вам огромное.
Открыл глаза
Сообщения: 57
Зарегистрирован: Пн апр 08, 2019 11:03:59

Сообщение Serg290 »

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

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

if (isBitSet(&Var_70,1)){ //Вызываю в функции из регистра
Func_27B();
Не компилируется. Что не так я делаю?
Заранее спасибо за помощь.
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

Я сейчас точно не помню как реализован синтаксис абсолютного адреса конкретно в XC8 и XC16, но общее правило - это спецификатор at или @ в объявлении переменной.
uint8_t var __at(0x1000);
Открыл глаза
Сообщения: 57
Зарегистрирован: Пн апр 08, 2019 11:03:59

Сообщение Serg290 »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4703911#p4703911"]Я сейчас точно не помню как реализован синтаксис абсолютного адреса конкретно в XC8 и XC16, но общее правило - это спецификатор at или @ в объявлении переменной.
uint8_t var __at(0x1000);[/uquote]
Спасибо большое!!! uint8_t Var_70 __at(0x70); ПРОКАТИЛО!!! XC8
Родился
Аватара пользователя
Сообщения: 19
Зарегистрирован: Сб окт 04, 2014 10:16:04

Сообщение Катэ911 »

Привет. Я пытаюсь изучить программирование 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:
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Не вникал в логику, но строчка

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

return flag_up, flag_dn;
по сути эквивалентна

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

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

Если надо иметь на выходе функции единицу, если хоть один флаг выставлен, то используйте или лог.ИЛИ или даже побитное ИЛИ.

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

return flag_up | flag_dn;
Друг Кота
Аватара пользователя
Сообщения: 25398
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="uldemir",url="/forum/viewtopic.php?p=4717462#p4717462"]Если надо иметь на выходе функции единицу, если хоть один флаг выставлен, то используйте или лог.ИЛИ или даже побитное ИЛИ.[/uquote]
Или можно сразу объявить структуру с полями flag_up и flag_dn, тогда return сможет вернуть оба значения одновременно.
Правда нужно помнить, что вызов функции в условии, где поочередно проверяются поля структуры возвращаемой функцией, сама функция будет вызываться столько раз, сколько полей проверяется (тут два поля). Что не торт. Поэтому лучше сначала значение функции буферизовать в локальную переменную того же типа.

ЗЫ. По существу вопроса.
А зачем вообще возвращать значение функции, если ГЛОБАЛЬНЫЕ переменные имеют это самое значение?
Бессмыслица.
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Пт мар 29, 2013 23:53:14

Сообщение ALEKS1102X »

[uquote="Катэ911",url="/forum/viewtopic.php?p=4717451#p4717451"]Привет. Я пытаюсь изучить программирование PIC на си.
Сочинил в mplab x простую программу под xc8 v2.50
...


I need help. :cry:[/uquote]

Доброй ночи!
Могу предложить тестовый проект: https://drive.google.com/file/d/1_XUKBT ... sp=sharing

Возможно, найдёте что-то что поможет в освоении пиков.
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Пт мар 29, 2013 23:53:14

Сообщение ALEKS1102X »

Добрый день!

Для Катэ911:

У Вас очень плохо организован опрос кнопок :)
Опросить пин ... подождать 15 миллисекунд - чтобы ещё раз опросить .... (см. скрин 1) хм...

Далее, Вам нужно ДВА флага для ваших кнопок. Зачем используете ДВА байта ?
Далее, Вы используете всего ОДИН флаг кнопок - или ПЛЮС или МИНУС, зачем тогда используете ДВА байта, и не исключаете использование второго - в случае если кнопка ПЛЮС зафиксирована?

Далее, Вы пришли в основной (майн) код. Вы собираетесь только этим заниматься, или там будет ещё куча всяких действий?

Так может не нужно просиживать по 15 - 100 миллисекунд без всяких других действий?
Может просто организовать некий тайминг с прерыванием на основе ЛЮБОГО свободного таймера, настроить его на некую константу прерываний, а всё остальное (включая задержки)
пусть пляшет от того тайминга (см. скрин 2).

В общем, я немного подправил Ваш исходник, но по уму - его нужно переписать с нуля :)
https://drive.google.com/file/d/1Grr_Yh ... sp=sharing

Добавлено after 56 minutes 20 seconds:
https://drive.google.com/file/d/1mQ8JaI ... sp=sharing
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Пт мар 29, 2013 23:53:14

Сообщение ALEKS1102X »

Встал на лапы
Сообщения: 138
Зарегистрирован: Вс окт 11, 2009 09:54:59
Откуда: Пенза

Сообщение Darkmaster »

всем привет )
сразу,у меня это одно из хобби.экспериментатор(как в песенке группы Алиса)
это в общем то не совсем по языку Си ,но про Pic мк.я решил не создавать новую тему,если что сделаем.

вопрос по такому.
в МК есть аппаратные сбросы по WDT/POR/BOR,флаги их..
как мне правильно это все обрабатывать?

например мк(устройство работало штатно) произошел сброс по снижению напряжения питания.1секунда потери например.
цель - для пользователя это просто моргнул индикатор,все работает ка и было.
возьмем что то,часы пусть.
при сбросе адрес выполнения программы переходит на 0x0000,получатся начало ?

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

main(_)
{...
т.е. проверять флаги,ЧП сброса в начале программы,до основного цикла ( while))
правильно я понимаю ?
в общем случаем как тут быть,писать флаг что все,хорошо,затем при сбросе его проверить-если что то запуск индикатора и т.д.(часы)
но если это более серьезное ,например эбу авто.
как узнавать что на 1сек был затык ,и вернуться к норм работе?
(это конечно грубый пример,там все серъезн)


получается я могу программно проверить только в главных функциях main()
isr (interrupt )?
как понять что система работала-сброс-опа,питание упало поднялось,это было включено.это нет ,идем сюда...?


сумбурно немного :roll: но так
Интересная,однако,штука
Поставщик валерьянки для Кота
Сообщения: 1916
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария

Сообщение veso74 »

После ресета, до main() проверить регистр PCON: POWER CONTROL REGISTER -> Determining the Cause of a Reset
Будет ли МК что-то делать или нет потом, зависит от поставленных задач.

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

The Power Control (PCON) register contains flag bits to differentiate between a:
• Power-on Reset (POR)
• Brown-out Reset (BOR)
• Reset Instruction Reset (RI)
• MCLR Reset (RMCLR)
• Watchdog Timer Reset (RWDT)
• Stack Underflow Reset (STKUNF)
• Stack Overflow Reset (STKOVF)
Изображение
Контактная информация:
Встал на лапы
Сообщения: 138
Зарегистрирован: Вс окт 11, 2009 09:54:59
Откуда: Пенза

Сообщение Darkmaster »

[code
#include "main.h"

#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000L //4Mgz
#endif




__CONFIG(UNPROTECT&BORDIS&MCLRDIS&PWRTDIS&WDTDIS&INTIO&LVPDIS);


int temper = 0;
int time_h = 0;
int time_m = 0;
char time_buf[6];


void interrupt isr(void)
{


}


void init(void)
{ CLRWDT();
OPTION = 0b00000000; //internal OSC ,1:2
INTCON = 0b00000000; // interrupts at peripheral
PIE1 = 0b00000000; //tmr1 and ctmr 2 off
PIR1 = 0b00000000;

PCON = 0b00001011; // OSC 4MHz
CMCON = 0b00000111;
VRCON = 0b00000010;
TXSTA = 0b00000010;
RCSTA = 0b00000000;
PORTA = 0b00000000;
PORTB = 0b00000000;
TRISA = 0b00000000;
TRISB = 0b00000000;
GIE = 0;
}
void main(void)
{ Тут прверка ЭТИХ БИТОВ СБРОСА ???????
init();
lcd_init();
// INIT_DS();
temper = 0x01;

sprintf(time_buf,"%d",temper);

lcd_puts(time_buf);

while(1)

{
temper = 0x06;[/code]
Интересная,однако,штука
Ответить

Вернуться в «PIC»