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

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

Сб дек 16, 2017 19:39:00

Да, с этим уже разобрался, спасибо!

А как перевести из float в int / unsigned int?

2.5*(5.0*ADRESH/(256.0)) - 1.0; - Вот это хотел бы перевести в int.

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

Сб дек 16, 2017 21:34:24

Вы занимаетесь отчаянной ерундой.
Никакого флоата не требуется.
Вы пытаетесь считать на МК как на калькуляторе. Это совершенно пустое мероприятие.
Для чего Вам нужны вольты?

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

Сб дек 16, 2017 22:07:46

Поясняю, для чего:

Я через вольты написал приблизительную функцию для нажатой клавиши:

0,4 В - 0
0,8 В - 1
и так далее.

Но увы, придется нажатие клавиш разных чисто через ADRESH обрабатывать, что некрасиво, увы.

P.S. Есть гайд небольшой, по работе с LCD? (lm016l - если конкретно).
Последний раз редактировалось SpeedFighter Сб дек 16, 2017 22:41:33, всего редактировалось 1 раз.

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

Сб дек 16, 2017 22:37:13

Это апокалиптический бред.
Вместо внятного дефайна константы сравнения Вы считаете никому не нужный флоат.
Уважаемый, Вам бы основы программирования почитать, прежде чем писать код...
ЗЫ. Вывод на дисплей тоже не требует флоата. На дисплей выводят ДВОИЧНО-ДЕСЯТИЧНОЕ ЦЕЛОЕ ЧИСЛО, а не флоат. Точку зажигают в необходимой позиции независимо от расчета цифр в разрядах.

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

Вс дек 17, 2017 07:19:38

Понял, ладно.

Но библиотеку для работы с LCD все равно не могу найти для PIC.

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

Вс дек 17, 2017 09:22:23

А к чему она?
Есть даташит на ЖК, вот и напишите драйвер сами.

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

Вс дек 17, 2017 10:15:15

Мне так удобнее было бы разобраться.

Так-то вот, нашел один код, который я в проект свой вставил:

Спойлер
Код:
/*
 * File:        newmain.c
 * Автор:       ViktoR
 * Программа:   Передача параметров с клавиатуры
 * Создана:     15 декабря 2017 г., 15:44
 */

// Подключаем библиотеки
#include <stdio.h>      // Стандартная библиотека Си для ввода-вывода
#include <stdlib.h>     // Стандартная библиотека Си для контроля
#include <xc.h>         // Библиотека компилятора XC8 для работы с PIC

// Определение параметров микроконтроллера
#define _XTAL_FREQ 16000000     // Тактовая частота 16 МГц (см. OSCCON)
#define DELAY_ADC 10            // Задержка АЦП, в мс

// Определение параметров для подключение периферии
// Светодиоды
#define LED_ERROR RB6   // Светодиод, индицирующие статус набора (ошибка)
#define LED_OK RB7      // Светодиод, индицирующие статус набора (норм)
#define KEYBOARD AN0    // Определяем порт для подключения клавиатуры через АЦП
// ВАЖНО: ПОРТ ДОЛЖЕН ПОДДЕРЖИВАТЬ АНАЛОГОВЫЕ СИГНАЛЫ (НАЗЫВАТЬСЯ AN)
//  LCD биты и переменные
#define LCD_width  15   //  Ширина дисплея
#define LCD_height 1    //  Высота дисплея
#define RS_1 RB6 = 1    //  RC0
#define RS_0 RB6 = 0    //  RC0
#define E_1  RB5 = 1    //  RA0
#define E_0  RB5 = 0    //  RA0

// LCD биты и переменные:
const unsigned char addLUT[4] = {0x80, 0xC0, 0x94, 0xD4};
unsigned char LCD_Address, LCD_Line;
char buffer[15];

void delay(unsigned int p)
{
    unsigned int i;
    for(i=0;i<p ;i++){asm("NOP");}
}

//  LCD
void WriteNibble(unsigned char data)
{
    E_1;
    PORTC = (data & 0x0F)*16;
    E_0;
    delay(300);
}

void WriteByte(unsigned char data)
{
    E_1;
    PORTC = (data >> 4)*16;
    E_0;
    E_1;
    PORTC = (data & 0xF)*16;
    E_0;
    delay(300);
}

void SetLCDPosition(char row, char col)
{
    RS_0;
    WriteByte(addLUT[row] + col);
    RS_1;
    LCD_Address=col;
    LCD_Line = row;
}

void ClearLCD(void)
{
    RS_0;
    WriteByte(0x01);
    delay(1000);
    RS_1;
    SetLCDPosition(0,0);
}

void ShowChar(unsigned char c)
{
    RS_1;
    WriteByte(c);
    LCD_Address++;
    if(LCD_Address>LCD_width)
        if(LCD_Line<LCD_height)
            SetLCDPosition(LCD_Line+1,0);
        else
            SetLCDPosition(0,0);
}

void ShowStr(unsigned char *s)
{
    while (*s != 0) ShowChar(*s++);
}

void InitLCD(void)
{
    int i;
    E_0;
    RS_0;
    delay(5000);
    WriteNibble(0x33);
    WriteNibble(0x33);
    WriteNibble(0x33);
    WriteNibble(0x22);
    WriteByte(0x28);
    WriteByte(0x01);
    WriteByte(0x10);
    WriteByte(0x06);
    WriteByte(0x0C);
    for(i=0x40; i < 0x5F; i++)
    {
        delay(1000);
        RS_0;
        WriteByte(i);
        delay(1000);
        ShowChar(0);
    }
    RS_1;
    SetLCDPosition(0, 0);
    buffer[0] = 'O';
    buffer[1] = 'k';
    buffer[2] = '\0';
    ShowStr(buffer);
}
//  -LCD биты

/*// Объявляем глобальные переменные:
int gNumber[5] = {0}; // Массив с разрядами набранного числа*/

// Объявляем используемые функции
void Prepare();             // Функция подготовки МК (настройка портов и т.п.)
int get_Number();           // Функция получения набранного номера
void DelLastNumb(int i);    // Функция удаления последней цифры
void StartADC();            // Функция запуска АЦП

int main()  // Главная функция
{
    // Определяем локальные переменные:
    /*int key, i = 0;    // Переменные для определения нажатой кнопки и разрядности соотвественно
    float Middle;      // Костыльная переменная*/
   
    // Вызываем нужные функции:
    Prepare();  // Вызов функции подготовки 
    delay(100);
    InitLCD();  //  инициализация дисплея
    delay(10000);
    ClearLCD(); //  очистка дисплея
    ShowStr("Test1");   //  вывод строки*/
   
   
    /*while(1)    // Бесконечный цикл работы МК
    {
        PORTC = ADRESH;
        // Проверка на окончание преобразование АЦП и фильтрация шумов)
        if((ADCON0bits.GO == 0))   
        {   
            if(ADRESH > 15)
            {
                LED_OK = 1;
                LED_ERROR = 0;
                StartADC();
            }
            else
            {
                LED_OK = 0;
                LED_ERROR = 1;
                StartADC();
            }
        }
    }*/
    return 0;
}

// Описание функции подготовки (настройки) параметров МК
void Prepare()
{
    // Настройки МК:
    OSCCON = (1<<4)|(1<<5)|(1<<6);  // Установка IRCF = '111' для частоты в 16 MHz
    ADCON1bits.VCFG0 = 0;           // Установка опорного напряжения
    ADCON1bits.VCFG1 = 0;           // Установка опорного напряжения
    TRISA = 0b1111111;              // Ножки RA0 - R7 - вход
    TRISB = 0b0000000;              // Ножки RB0-RB7 - выход
    TRISC = 0b0000000;              // Ножки RC0-RC7 - выход
    ANCON0 = 1;                     // AN как аналоговый входы
    // Настройки АЦП:
    ADCON2bits.ACQT = 1;            // 2 = 4TAD
    ADCON2bits.ADCS = 0b010;        // 16 TOSC
    ADCON0bits.CHS4 = 0;            // Настройка входа АЦП (AN0)
    ADCON0bits.CHS3 = 0;            // Настройка входа АЦП (AN0)
    ADCON0bits.CHS2 = 0;            // Настройка входа АЦП (AN0)
    ADCON0bits.CHS1 = 0;            // Настройка входа АЦП (AN0)
    ADCON0bits.CHS0 = 0;            // Настройка входа АЦП (AN0)
    ADCON2bits.ADFM = 0;            // Левое выравынивание
    ADCON0bits.ADON = 1;            // Включили модуль АЦП
    PIR1bits.ADIF = 0;              // Сброс прерываний АЦП
    PIE1bits.ADIE = 0;              // Разрешили прерывание АЦП
    INTCONbits.PEIE = 0;            // Периферийные прерывания разрешены
    INTCONbits.GIE = 0;             // Глобальные прерывания разрешены
    ADCON0bits.GO = 1 ;             // Метка начала преобразования
}

/*// Описание фунцкии удаления последнего номера:
void DelLastNumb(int i)
{
   if(i == 0)
   {
      gNumber[0] = 0;
   }
   for(int j = 0; j <= i; j++)
   {
      if (j == i)
      {
         gNumber[j] = 0;
      }
      else
      {
         gNumber[j] = gNumber[j+1];
      }
   }
}*/

// Описание функции получения числа
/*int get_Number()
{
   return (gNumber[4]*10000 + gNumber[3]*1000 + gNumber[2]*100 + gNumber[1]*10 + gNumber[0]);
}*/

// Описание функции запуска АЦП
void StartADC()
{
    __delay_ms(DELAY_ADC);  // Задержка перед началом АЦП
    ADCON0bits.GO = 1 ;     // Метка начала преобразования
}


Жаль только, что что слишком часто сменяются надписи Ok и Test, но это задержки тут кривые, наверное.

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

Пн фев 19, 2018 17:55:16

Что скажете по поводу компилятора sdcc? Он вроде как умеет pic16/18 и бесплатный?

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

Вт мар 13, 2018 18:45:25

ниид хелп. Компилятор XC8 не хочет проглатывать такую простую конструкцию
Код:
=RC1REG
Мне нужно его просто прочитать, но данные сохранять не нужно. Почему-то казалось, что это вполне легальная конструкция.

Спойлерконтекст:
Код:
    if (RCIE && RC1IF) {
        RC1IF = 0;
        if (FERR == 1) {
            FERR = 0; // framing error clear, but skip data
            =RC1REG;
        } else {
            if (uart_count < UART_BUFFER_SIZE) {
                *wr_ptr = RC1REG;
                uart_count++;
                if (++wr_ptr > &uart_buf[UART_BUFFER_SIZE]) wr_ptr = uart_buf;
            }
        }
    }
Последний раз редактировалось uldemir Вт мар 13, 2018 18:54:17, всего редактировалось 1 раз.

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

Вт мар 13, 2018 18:51:06

Может надо RCREG1 ? и что пишет то при компиляции?

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

Вт мар 13, 2018 18:55:01

Перед знаком "=" всегда должен стоят "адресат".
Просто прочитать можно написав имя регистра без всяких лишних знаков.

Добавлено after 3 minutes 25 seconds:
А вообще, в Вашем коде можно сделать чтение регистра во временную переменную, вначале условия, а потом уже работать с ней. Т.к. :
1. Он в коде у Вас 2 раза читается.
2. Компилятор, в любом случае, выделит место для его чтения.

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

Вт мар 13, 2018 19:16:33

Не читается - второе под условием else - будет или один или второй. Думал, может кто замечание по реализации кольцевого буффера скажет... чёрт, вижу еще один затык: если буфер переполнен, то я тоже не читаю регистр, а флаг прерывания снимаю - тоже может повиснуть и не отвиснуть.

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

Вт мар 13, 2018 19:28:33

Вы, по всей видимости, меня не поняли.
Код:
    if (RCIE && RC1IF) {
        unsigned char rcreg=RC1REG;
        ..............
        ..............

И дальше читаем переменную rcreg где нужно. А RC1REG будет прочитан всегда, когда вызовется прерывание.

Добавлено after 4 minutes 17 seconds:
Кстати, RC1IF = 0; - бесполезное действие. Он сбрасывается аппаратно, при чтении регистра RCREG.

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

Вт мар 13, 2018 21:25:01

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

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

Вт мар 13, 2018 21:27:02

Тогда сделайте так, да и всё :
Код:
        if(FERR) {
            unsigned char rcreg=RC1REG;
        } else {

А остальное оставьте как есть.

PS: Проц какой ?

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

Ср мар 14, 2018 17:20:55

pic18f25k40. Cделал так:
Код:
    if (RCIE && RC1IF) {
        if (FERR == 1) { // framing error clear, but skip data.
            RC1REG;
        } else {
            if (uart_count < UART_BUFFER_SIZE) {
                *wr_ptr = RC1REG;
                uart_count++;
                if (++wr_ptr >= &uart_buf[UART_BUFFER_SIZE]) wr_ptr = uart_buf;
            } else RC1REG;
        }
    }
Поправил и кольцевой буфер, а то похоже, у меня на один байт дальше указатель вылетал. А объявлять локальную переменную в обработчике прерывания что-то желания нет. нет у меня доверия к этому компилятору в бесплатном режиме. Больше нет.

Еще вопрос. А как быть с EEPROM? как его проинициализировать? когда-то писал ORG 0x2000. А вот в С что-то не соображу. А до юзер мануала еще 3 часа ехать.

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

Ср мар 14, 2018 18:49:56

uldemir писал(а):Cделал так:

Как вариант :
Код:
    if (RCIE && RC1IF) {
        if (!FERR && (uart_count < UART_BUFFER_SIZE)) {
            *wr_ptr = RC1REG;
            uart_count++;
            if (++wr_ptr >= &uart_buf[UART_BUFFER_SIZE]) wr_ptr = uart_buf;
        }
        RC1REG;
    }
По алгоритму получается один в один.
А uart_count что делает ? И в какой момент сбрасывается ?

uldemir писал(а):нет у меня доверия к этому компилятору в бесплатном режиме.
А если сделать его "платным" ? :roll:
Какой компилятор, кстати ?
Если XC8, то на
uldemir писал(а):как быть с EEPROM? как его проинициализировать?
Мануал говорит следующее :
Изображение
2018-03-14_19-52-34.png
(25.71 KiB) Скачиваний: 518

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

Ср мар 14, 2018 19:37:07

Неплохой вариант. Я т пытался снахрапа взять. Собственно, еще одна ситуация не обрабатывается: OERR. Но, подумал, что это событие маловероятно, да и выход из него далеко не прост. Хотя, чё там не выключить и не включить обратно приём, раз уж данные и так потеряны?

uart_count у меня вычитается по мере считывания буфера в основном теле программы:
Код:
        if (uart_count) { // в буфере есть данные.
            uart_byte = *rd_ptr;
            uart_count--;
            if (++rd_ptr >= &uart_buf[UART_BUFFER_SIZE]) rd_ptr = uart_buf;

Может кольцевой буфер можно изящнее организовать? Надо посмотреть, как я сто лет назад его делал на 580-м процессоре...
Аlex писал(а):А если сделать его "платным" ?
да, это про XC8 - платный он дюже дорог. А триальными 60-ю днями я уже в прошлом году воспользовался и это счастье больше мне не светит. А обмануть, его можно было только до какой-то версии. Говорят, они теперь стали внутрь зашивать SHA256 файла проверяющего лицензию, поэтому подменить пустышкой его больше нельзя.

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

Ср мар 14, 2018 20:19:11

А зачем гнаться за этими версиями ? Можно пользоваться той версией, до которой лекарство подходит. Вряд ли они что-то там серьёзное исправляют и добавляют.

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

Ср мар 14, 2018 21:09:06

xc8 1.41 в windows и свежая 1.45 в linux легко были обмануты пургеном от старой 1.32 версии 2014г.
Ответить