реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> char + char = int как такое сделать, Сделать из двух байт целое
bugor
сообщение Aug 28 2009, 10:28
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 26-02-09
Пользователь №: 45 408



Цитата(tag @ Aug 28 2009, 13:57) *
Код
  *(pU) = ADRESH;             //старший байт в первый элемент массива
      *(pU++) = ADRESL;           //младший байт во второй элемент массива


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


Пост №10 там полный код приведен.
Go to the top of the page
 
+Quote Post
Kane
сообщение Aug 28 2009, 10:33
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 10-02-06
Пользователь №: 14 185



Цитата(tag @ Aug 28 2009, 13:57) *
Код
  *(pU) = ADRESH;             //старший байт в первый элемент массива
      *(pU++) = ADRESL;           //младший байт во второй элемент массива


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


Это есть. в самом верху...
Цитата(tag @ Aug 28 2009, 13:57) *
Код


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


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


Какой pic используется? Я глядел в описалово на 16f87x, так там для регистра ADCON0 бит 1 - не определён.
Получается, SETBIT(ADCON0,1); - просто не туда попадает.

Сообщение отредактировал Kane - Aug 28 2009, 10:38
Go to the top of the page
 
+Quote Post
bugor
сообщение Aug 28 2009, 10:45
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 26-02-09
Пользователь №: 45 408



ну так там написано в заголовке что pic12f675 rolleyes.gif

ёлки - чего еще обнаружил - этот компилятор не понимает вот это
Код
#asm
movwf OSCCAL
#endasm

а вот это понимает
Код
#asm
movwf 0x90
#endasm

хотя адрес этого регистра описан в хедере!
чегото мне подумалось, что если в этом такой глюк - чего говорить об указателях crying.gif

не подскажет ли кто поддерживает ли IAR мелкие процы, замучал меня чегото HT-TECH

Сообщение отредактировал bugor - Aug 28 2009, 11:00
Go to the top of the page
 
+Quote Post
Herz
сообщение Aug 28 2009, 11:28
Сообщение #19


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



С Хай-теком всё в порядке, Вы сами себя замучили такой кашей, компилятор тут ни при чём. Ни к чему здесь наверняка ни асм-овые вставки, ни хитрости с прерываниями. Разберитесь сначала с битами конфигурации, работой АЦП. Выравнивание происходит правильно? MPLAB используете? В нём всё просто и удобно. Для объединения байтов в int есть несколько вариантов. Я использовал такой:
Код
.......
     union {unsigned int wor; unsigned char by[2];} voltIN;
     .......
    
     Vcm.by[0]=ADRESL;            // младший байт
     Vcm.by[1]=ADRESH;            // старший байт
     .......
     HEXDEC(Vcm.wor);            // обращение к целому int-у
     .......

И зачем Вам это:
Код
<span class="postcolor">volatile unsigned int U[3];// @ 0x20;        //массив из трех двухбайтных элементов </span>

почему не просто:
Код
unsigned int U[3];        //массив из трех двухбайтных элементов
Go to the top of the page
 
+Quote Post
bugor
сообщение Aug 28 2009, 15:45
Сообщение #20


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 26-02-09
Пользователь №: 45 408



Ну вот что получилось - ацп работает но результата по прежнему толком нет.
В ацп есть какоето число но какое так и не смог выяснить.
Уже голову сломал не могу найти ошибку.
CODE
//;---------------------------------------
//; Процессор PIC12C672 или PIC12F675
//; Fosc = 4MHz Генератор RC-внутренний
//;---------------------------------------

#include <pic.h>

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

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

unsigned char Temp, Count, Channel;
unsigned int U[3]; //массив данных с 3х каналов

union{
unsigned int Vin;
struct{
unsigned char UL:8;
unsigned char UH:8;
} byte;
}volt;

#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 преобразования (ADCON1 после сброса уже установлен)
//================================
void InitAD() {
ADIE = 1; //Разрешить прерывания от АЦП
ADCON0 = Channel; //Генегатор внутр RC + номер канала
ADIF = 0; //очистить флаг прерывания от АЦП
PEIE = 1; //Разрешить переферийные прерывания
}
//==========================================================================
// MAIN
//==========================================================================
void main(void) {

#asm
bsf status,5 // КАЛИБРОВКА ГЕНЕРАТОРА !!!
call 0X3ff
movwf 0X90
bcf status,5
#endasm

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 =0b00010111; // F/8 и три канала аналоговый вход
warm_out = 1; // вкл выход

Count = 0; //первичная инициализация АЦП
Channel = 129;
InitAD();
ADDelay();
SETBIT(ADCON0,1);

while(1) { //бесконечный цикл

#asm
nop
nop
nop
nop
nop
nop
#endasm

if(U[0] < 2900 ) { //вот тут не работает при напряжении на ацп 3,8 вольт
sound_out = 1; //результат должен быть в районе 3114 а его нет
}else {
sound_out = 0;
}
}
}

//================================
//Обработка прерываний
//================================
void interrupt ADC() {

// sound_out = 1;

volt.byte.UL=ADRESL;
volt.byte.UH=ADRESH;
U[Count]=volt.Vin;

if(Count++ < 3) {
Channel = Channel + 8; //загрузить другой канал
}else {
Channel = 129; //10000001b загрузка канала АЦП 0
Count = 0; //перезагрузить счетчик каналов
}
InitAD();
ADDelay(); //задержка на 2xTad для восстановления

// sound_out=0;

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


Раньше писал для этого же процессора на асме и все работало - правда были мучения с вычислениями, а сейдас даже результата преобразования получить не могу - а ведь хотелось как быстрее и красивее smile.gif

Модератор. В очередной раз фиксирую нарушение Вами п.3.4 Правил форума. Либо упаковывайте цитаты исходников в тэги [ codebox ] самостоятельно, либо прилагайте их к сообщению в виде архива так, как это рекомендуют Правила форума.
С уважением, rezident.
Причина редактирования: Нарушение п.3.4 Правил форума.
Go to the top of the page
 
+Quote Post
Student Pupkin
сообщение Aug 28 2009, 18:45
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 23-05-08
Пользователь №: 37 760



Цитата(bugor @ Aug 28 2009, 19:45) *
Ну вот что получилось - ацп работает но результата по прежнему толком нет.

1) Есть предложение попробовать "unsigned unt U[3]" переобозвать в "volatile unsigned int U[3]".
2) (это так... мелочь.... smile.gif ) В функции ADDelay() к переменной-счетчику "static unsigned char i" тоже наверное желательно "volatile" присовокупить. А еще - зачем вы ее static сделали?
Go to the top of the page
 
+Quote Post
Herz
сообщение Aug 29 2009, 10:55
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Не пойму я, во-первых, зачем Вы структуру сюда прикрутили (было же просто и понятно), во-вторых, откуда у 10-разрядного АЦП возмётся результат больше, чем 1024, в-третьих, в обработчике прерывания флаг не очищается? И всё-таки: MPLAB есть? И почему бы не использовать примеры функций, включенных в HT-PICC? Там есть и для АЦП, и для программной задержки, и для прерываний...
Go to the top of the page
 
+Quote Post
bugor
сообщение Aug 29 2009, 17:14
Сообщение #23


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 26-02-09
Пользователь №: 45 408



1. В функции задержки переменная i только для счетчика и нигде больше не видна и не нужна - так что static.
2. Флаг ADIF сбрасывается в ноль в функции InitAD.
3. Попробую и volatile еще тем более, что изменяется в прерывании - раньше так и было но мне чего то код в асме не понравился вот и убрал.
4. Структуру прикрутил по совету выше и опыту проектов в IAR - да и скомпилировалось сразу без ошибок и по коду вроде все верно делает, объединяя два char в один int.
5. MPLAB есть но никогда им не пользовался так как есть среда ФИТОН но вот их hard-ключ уже третий раз глючит а пересылать в москву надоело и они чего то (как все нормальные конторы) за свой счет делать не предлагают - вот по этому HI-TECH........ И проблемы.
5. А вот в том что результат больше чем 1024 - ЭТО КОСЯК!!!! - какой меня дернуул думать что там 4096 - 12 бит!!!!!
ума не приложу wacko.gif Спасибо всем буду копать. КАК накопаю и получу рабочий код - расскажу.

Сообщение отредактировал bugor - Aug 29 2009, 17:22
Go to the top of the page
 
+Quote Post
XVR
сообщение Aug 29 2009, 18:18
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Вот это if(Count++ < 3) { должно быть так if(++Count < 3) {. Иначе у вас Count будет принимать значение 3, что выходит за границы массива U
Go to the top of the page
 
+Quote Post
Student Pupkin
сообщение Aug 29 2009, 18:39
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 23-05-08
Пользователь №: 37 760



Цитата(bugor @ Aug 29 2009, 21:14) *
1. В функции задержки переменная i только для счетчика и нигде больше не видна и не нужна - так что

Для локальных переменных класс памяти static означает, что переменная сохраняется между вызовами функции. Не видна - это когда static применяется к глобальным переменным. Или нет?
Однако тут на форуме говорили, что особо свирепый компилятор может так сильно "оптимизировать" подобную программную задержку, что ее совсем не будет (ну вроде как считаем без дела, время тратим, значит выкидываем). И вроде как для программной задержки переменную-счетчик надо объявлять volatile, чтоб оптимизацию над ней подавить...
Go to the top of the page
 
+Quote Post
Herz
сообщение Aug 29 2009, 18:47
Сообщение #26


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Цитата(bugor @ Aug 29 2009, 19:14) *
4. Структуру прикрутил по совету выше и опыту проектов в IAR - да и скомпилировалось сразу без ошибок и по коду вроде все верно делает, объединяя два char в один int.
Так там не нужна структура, достаточно объединения.
Цитата
5. MPLAB есть но никогда им не пользовался так как есть среда ФИТОН но вот их hard-ключ уже третий раз глючит а пересылать в москву надоело и они чего то (как все нормальные конторы) за свой счет делать не предлагают - вот по этому HI-TECH........ И проблемы.

И напрасно: MPLAB - удобная штука (может, бывают и получше среды, но не суть), осваивается легко, бесплатная, есть симулятор, чего же голову морочить...

Сообщение отредактировал Herz - Aug 29 2009, 18:48
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 31 2009, 18:28
Сообщение #27


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(bugor @ Aug 29 2009, 21:14) *
1. В функции задержки переменная i только для счетчика и нигде больше не видна и не нужна - так что static.
Ошибаетесь: static для локальной переменной функции и static для локальной переменной модуля имеют разный смысл.
Код
int get_cnt(void)
{
    ststic int cnt = 100;
    return (cnt++);
}

for (int i=0; i<3; i++)  get_cnt();
/*
    Вернёт:
    100
    101
    102
*/
rezident в следующем сообщении более грамотно изложил суть...
А для доступа к слову побайтно удобно пользоваться объединением с безымянной структурой (если Ваш компилятор это позволяет).
Код
typedef union
{
    uint16_t word;
    struct
    {
        uint8_t byte0;
        uint8_t byte1;
    };
} my_int16_t;

my_int16_t x = {.word = 0xABCD};

void swap_bytes(my_int16_t* x)
{
    uint8_t temp = x->byte0;
    x->byte0 = x->byte1;
    x->byte1 = temp;
}
Единственное о чём ещё следует позаботиться, так это о выравнивании полей структуры по границе байта
(#pragma pack(1) или через атрибуты или через makefile)...
И более того, даже так Вам не удастся избежать возможных граблей с big-little endian...
Единственное дубовое решение - это макросы со сдвигами типа:
Код
#define GET_BYTE(X,Y)  ((uint8_t)((X)>>((Y)*8)))
#define BYTE0(X)     GET_BYTE((X),0)
#define BYTE1(X)     GET_BYTE((X),1)
#define BYTE2(X)     GET_BYTE((X),2)
#define BYTE3(X)     GET_BYTE((X),3)
...
#define LH2WORD(LBYTE,HBYTE)      ((uint16_t)((HBYTE)<<8) | (LBYTE))


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 31 2009, 18:36
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Student Pupkin @ Aug 30 2009, 00:39) *
Для локальных переменных класс памяти static означает, что переменная сохраняется между вызовами функции. Не видна - это когда static применяется к глобальным переменным. Или нет?
Для переменных типа static выделяется постоянное место в ОЗУ, точно также, как и для глобальных переменных. И инициализация static начальным значением (очистка, если значение явно не задано) осуществляется точно также, как и у глобальных переменных. Но область видимости переменной типа static действительно ограничена, также, как и у автоматической (локальной) переменной. Тут вы правы.
Go to the top of the page
 
+Quote Post
bugor
сообщение Sep 6 2009, 14:41
Сообщение #29


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 26-02-09
Пользователь №: 45 408



Ну вот собственно заработало.
Проиллюстрирую поподробнее, может пригодится кому.
Обязательно надо настроить все переиферийные устройства, не полагаясь на автоматические установки после сброса.

Это переменная куда заносятся байты результата. Главное, чтобы они были именно в этом порядке.
Пока сделал так - потом без структуры попробую.
CODE
union{
volatile unsigned int Vin;
struct{
volatile unsigned char UL:8;
volatile unsigned char UH:8;
} byte;
}volt;

Это программы задержки и переинициализации АЦП
CODE
void ADDelay() { //задержка 10uS
static unsigned char i;
i = 3; //Генератор 4Mhz, период 3uS,
while(i > 0) { //переменная равна 3 плюс смещение
i--;
}
}
void InitAD() {
ADIE = 1; //Разрешить прерывания от АЦП
ADCON0 = Channel; //Генегатор внутр RC + номер канала
ADIF = 0; //очистить флаг прерывания от АЦП
PEIE = 1; //Разрешить переферийные прерывания
}


Это необходимые процедуры для запуска АЦП
CODE
void main(void) {

#asm
bsf status,5 // КАЛИБРОВКА ГЕНЕРАТОРА !!!
call 0X3ff
movwf 0X90
bcf status,5
#endasm

WPU = 0; // все подтягивающие резисторы выключены
ANSEL = 0b01010011; // F/16 для АЦП и 2 канала аналоговых
GPIO = 0b00000000; // порты в ноль
TRISIO = 0b00001111; // GP4-5 на выход
OPTION = 0b10000111; // R-up выкл, делитель 1:256 к TMR0
VRCON = 0x00; // выключить источник опорного напряжения
IOCB = 0x00; // запрет прерываний по входам
CMCON = 0b00000111; // выключить компаратор
INTCON = 0b10000000; // разрешить общее прерывание

Count = 0; //первичная инициализация АЦП
Channel = 129;
InitAD();
ADDelay();
SETBIT(ADCON0,1);

while(1) { //бесконечный цикл
#asm
nop
nop
nop
nop
nop
nop
#endasm
......................................
//основная программа
......................................

}
}

А это обработка прерывания АЦП.
CODE
void interrupt ADC() {

if(ADIF == 1) {

volt.byte.UL=ADRESL; //ВОТ В ЭТИХ ТРЕХ СТРОКА ФОРМИРУЕТСЯ МАССИВ РЕЗУЛЬТАТОВ АЦП
volt.byte.UH=ADRESH; //В ДАННОМ СЛУЧАЕ - ЭТО ДВА ЦЕЛЫХ ЧИСЛА
U[Count]=volt.Vin; //ТУТ ПОЛУЧАЕМ ЦЕЛОЕ С ПРАВИЛЬНЫМ РАСПОЛОЖЕНИЕМ БАЙТОВ
//ПРИ ДАЛЬНЕЙШЕЙ МАТЕМАТИЧЕСКОЙ ОБРАБОТКЕ ВСЕ ПРОИСХОДИТ ПРАВИЛЬНО

if(++Count < 2) {
Channel = Channel + 4; //загрузить другой канал
InitAD();
ADDelay(); //задержка на 2xTad для восстановления
ADDelay();
SETBIT(ADCON0,1);
}else {
Channel = 129; //10000001b загрузка канала АЦП 0
Count = 0; //перезагрузить счетчик каналов
InitAD();
ADDelay();
ADDelay();
SETBIT(ADCON0,1);
}
}

............................
//Тут могут быть обработчики других прерываний
...........................
}


Итого был неправильно оформлен счетчик массива, разрядность АЦП 12 бит вместо десяти ну и обьединение для собственно запихивания байт в целое.
Всем спасибо!
Причина редактирования: Уменьшение горизонального размера цитаты.
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 13:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01499 секунд с 7
ELECTRONIX ©2004-2016