Перейти к содержанию
    

char + char = int как такое сделать

Ситуатция известная -

- результат АЦП их двух байт в разных банках.

- работает три канала.

- есть массив из трех int.

Надо младший и старший байты результата АЦП обьединить в три целых переменных в массиве.

 

Чегото не получается никак - уже который раз пытаюсь. В AVR наких проблем нету, а на PIC редко пишу - направьте где посмотреть как это делается? Надо на СИ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это не подойдёт?

int result = ((int)highByte << 8) + lowByte;

 

HTEC PIC ругается - degenerate unsigned comparison

 

volatile unsigned int U[3] @ 0x20; //массив

 

ADRESH и ADRESL - это байты результата

 

надо в U[0] поместить ADRESH и ADRESL первого преобразования

в U[1] -----------------------------------второго преобразования и тд

 

Ммссив надо как то в цикле индексировать по счетчику каналов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

За правильность не ручаюсь, т.к. с пиками давно не работал, а в HTEC PIC вообще не писал. :)

char i;
for (i = 0; i < 3; i++)
{
   ADCON0 &= 0xC3;     // сброс выбора входа
   ADCON0 |= (i<<3);    // выбор входа

   // тут надо вставить задержку

   ADCON0 |= (1<<2);  // запуск преобразования
   while (ADCON0 & (1<<2));  // ожидание завершения преобразования
   u[i] = ADRESH;
   u[i] <<=8;
   u[i] +=ADRESL;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

HTEC PIC ругается - degenerate unsigned comparison
Видимо потому, что перед сдвигом надо приводить к типу unsigned int, а не (signed) int. Или использовать временную локальную переменную типа unsigned int .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А нельзя типа такого?

short int adc_mass[3];  // или int16_t в духе С99 ??? 
char *adc_byte;           // или int8_t в духе С99 ??? 
adc_byte = (char*)adc_mass;
*(adc_byte++) = LOW_BYTE_ADC1;    // не знаю как называются, но 
*(adc_byte++) = HIGH_BYTE_ADC1;  // допустим так...
/*
и т.д. для остальных каналов АЦП
*/

Я есесно в пиках и хитеке ни гугу. Это, так сказать, лишь идея.... :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

За правильность не ручаюсь, т.к. с пиками давно не работал, а в HTEC PIC вообще не писал. :)

 

Скомпилировался и в железе запустился вроде - что за значения получаются завтра проверю. Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

char как и int - переменные со знаком. Если не знаете зачем вам нужен знак используйте unsigned.

И компилятор тут не при делах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А нельзя типа такого?

 

Не работает - преобразование вешается, я с указателями пробовал и не работает с ними у меня этот компилятор - не пойму почему.

Судя по листингу он сам активно использует косвенную адресацию и гдето там и происходит глюк, а как найти не знаю.

Вот полный код который компилируется но не работает - подскажите где ошибка.

//---------------------------------------
// Процессор PIC12F675
// Fosc = 4MHz  Генератор RC-внутренний
// HI-TECH 8.05LP1
//---------------------------------------

#include <pic.h>
#include <math.h>

__CONFIG(WDTDIS & INTIO & UNPROTECT & MCLRDIS & PWRTEN & BOREN );

#define warm_out   GPIO5	//выход нагревателя
#define sound_out  GPIO4	//выход pреле звука
#define start_out  GPIO3	//вход выключателя нагрева

volatile unsigned char Temp, Count, Channel;
volatile unsigned int U[3];// @ 0x20;		//массив из трех двухбайтных элементов 
volatile unsigned char *pU =(char*)U;		//указатель на адрес 1го элемента массива

//МАКРОСЫ
//-----------------------------------------
#define TESTBIT(ADRESS,BIT) (ADRESS & (1<<BIT))
#define SETBIT(ADRESS,BIT) (ADRESS |= (1<<BIT))
#define CLEARBIT(ADRESS,BIT) (ADRESS &= ~(1<<BIT))
//================================
//задержка для A/D преобразования
//================================
void ADDelay() {				 //задержка 10uS
static unsigned char i;
   i = 3;				  //Генератор 4Mhz, период 3uS,
   while(i > 0) {		  //переменная равна 3 плюс смещение
		i--;
   }
}
//================================
//Инициализация A/D преобразования
//================================
void InitAD() {
   ADIE = 1;				  //Разрешить прерывания от АЦП
   ADCON0 = Channel;		  //Генегатор внутр RC + номер канала
   ADIF = 0;				  //очистить флаг прерывания от АЦП
   PEIE = 1;				  //Разрешить переферийные прерывания
   asm("nop");
}
//==========================================================================
//		   MAIN
//==========================================================================
void main(void) {

GPIO = 0b00000000;	  // порты в ноль
TRISIO = 0b10001111;	// GP4-5 на выход
OPTION = 0b00000110;	// R-up выкл, делитель 1:128 к TMR0
VRCON = 0x00;		   // выключить источнок опорного напряжения
WPU = 0b00000000;	   // gp0 gp5 подтягивающие резисторы выключены
IOCB = 0x00;			// запрет прерываний по входам
CMCON = 0b00000111;	 // компаратор выключен
INTCON =0b10000000;	 // разреш прерывания
ANSEL =0b01010111;
warm_out = 1;

Count = 0;			  //первый запуск ацп
Channel = 129;		  //канал ацп 0
InitAD();
ADDelay();
SETBIT(ADCON0,1);

while(1) {
	 ei();
	 asm("nop");
	 di();
}
}
//================================
//Обработка прерываний
//================================
void interrupt ADC() {

  sound_out = 1;			 //индикатор работы ацп

  *(pU) = ADRESH;			 //старший байт в первый элемент массива
  *(pU++) = ADRESL;		   //младший байт во второй элемент массива
							  //точно также в 3-4 и в 5-6 элементы по циклу
  if(Count++ < 3) {
	Channel = Channel + 8;	 //загрузить другой канал
  }else {
	Channel = 129;			//10000001b загрузка канала АЦП 0 
	Count = 0;				//перезагрузить счетчик каналов
	*pU = U[0];			   //перегружаем адрес первого элемента массива
  }

  InitAD();
  ADDelay();			   //задержка на 2xTad для восстановления

  sound_out=0;

  ADDelay();
  SETBIT(ADCON0,1);		 //Запуск A/D преобразования
}

 

По посту №4 работает АЦП и даже есть результат но понятно это по изменению младшего байта результата, а вот когда пытаюсь запихать два байта в целое то сравнения не работают то есть не получается нормальног INT из двух CHAR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот на что обратил внимание:

 

    while(1) {
         ei();
         asm("nop");
         di();
    }

 

Зачем в цикле запрещаете прерывания и снова разрешаете (если я правильно угадал смысл ei() и di())?

 

      *(pU) = ADRESH;             //старший байт в первый элемент массива
      *(pU++) = ADRESL;           //младший байт во второй элемент массива
                                  //точно также в 3-4 и в 5-6 элементы по циклу

 

в этом куске младший байт всегда будет перетираться старшим байтом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот на что обратил внимание:

 

Зачем в цикле запрещаете прерывания и снова разрешаете (если я правильно угадал смысл ei() и di())?

 

в этом куске младший байт всегда будет перетираться старшим байтом.

 

После запрещения прерывания будут вычисления и чтобы в момент вычислений не изменились данные по прерыванию АЦП так сделано.

 

Я уже посмотрел по листингу что происходит затирка, а как сделать чтобы этого небыло не знаю.

Но дело еще в том, что код не работает не в смысле неправильного формирования данных а в том смысле что преобразования АЦП не производятся - то есть на выходе индикатора должен быть что то подобие меандра, а ничего не происходит - висит 1 - то есть в прерывание вход есть, а выхода нет :wacko:

Причем это наблюдается если начинаю использовать указатели - если без них то циклическое преобразование есть - но с данными непонятно что происходит.

Изменено пользователем bugor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После запрещения прерывания будут вычисления

При зазоре в один ноп могут быть очень большие проблемы с прерываниями. У пика конвейер из 4 слов, насколько припоминаю...

 

Не запрещайте прерываний без четкого понимания - для чего именно вам это нужно именно в данный момент. В данной программе данный код не имеет смысла. Даже для якобы будущих вычислений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  *(pU) = ADRESH;             //старший байт в первый элемент массива
      *(pU++) = ADRESL;           //младший байт во второй элемент массива

 

не понятно где и как инициализируется pU?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...