|
char + char = int как такое сделать, Сделать из двух байт целое |
|
|
|
Aug 28 2009, 10:28
|
Участник

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

|
Цитата(tag @ Aug 28 2009, 13:57)  Код *(pU) = ADRESH; //старший байт в первый элемент массива *(pU++) = ADRESL; //младший байт во второй элемент массива не понятно где и как инициализируется pU? Пост №10 там полный код приведен.
|
|
|
|
|
Aug 28 2009, 10:33
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 28 2009, 10:45
|
Участник

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

|
ну так там написано в заголовке что pic12f675  ёлки - чего еще обнаружил - этот компилятор не понимает вот это Код #asm movwf OSCCAL #endasm а вот это понимает Код #asm movwf 0x90 #endasm хотя адрес этого регистра описан в хедере! чегото мне подумалось, что если в этом такой глюк - чего говорить об указателях  не подскажет ли кто поддерживает ли IAR мелкие процы, замучал меня чегото HT-TECH
Сообщение отредактировал bugor - Aug 28 2009, 11:00
|
|
|
|
|
Aug 28 2009, 11:28
|

Гуру
     
Группа: Модераторы
Сообщений: 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]; //массив из трех двухбайтных элементов
|
|
|
|
|
Aug 28 2009, 15:45
|
Участник

Группа: Участник
Сообщений: 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 преобразования } Раньше писал для этого же процессора на асме и все работало - правда были мучения с вычислениями, а сейдас даже результата преобразования получить не могу - а ведь хотелось как быстрее и красивее Модератор. В очередной раз фиксирую нарушение Вами п.3.4 Правил форума. Либо упаковывайте цитаты исходников в тэги [ codebox ] самостоятельно, либо прилагайте их к сообщению в виде архива так, как это рекомендуют Правила форума. С уважением, rezident.
Причина редактирования: Нарушение п.3.4 Правил форума.
|
|
|
|
|
Aug 28 2009, 18:45
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 23-05-08
Пользователь №: 37 760

|
Цитата(bugor @ Aug 28 2009, 19:45)  Ну вот что получилось - ацп работает но результата по прежнему толком нет. 1) Есть предложение попробовать "unsigned unt U[3]" переобозвать в " volatile unsigned int U[3]". 2) (это так... мелочь....  ) В функции ADDelay() к переменной-счетчику "static unsigned char i" тоже наверное желательно "volatile" присовокупить. А еще - зачем вы ее static сделали?
|
|
|
|
|
Aug 29 2009, 10:55
|

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

|
Не пойму я, во-первых, зачем Вы структуру сюда прикрутили (было же просто и понятно), во-вторых, откуда у 10-разрядного АЦП возмётся результат больше, чем 1024, в-третьих, в обработчике прерывания флаг не очищается? И всё-таки: MPLAB есть? И почему бы не использовать примеры функций, включенных в HT-PICC? Там есть и для АЦП, и для программной задержки, и для прерываний...
|
|
|
|
|
Aug 29 2009, 17:14
|
Участник

Группа: Участник
Сообщений: 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 бит!!!!! ума не приложу  Спасибо всем буду копать. КАК накопаю и получу рабочий код - расскажу.
Сообщение отредактировал bugor - Aug 29 2009, 17:22
|
|
|
|
|
Aug 29 2009, 18:39
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 23-05-08
Пользователь №: 37 760

|
Цитата(bugor @ Aug 29 2009, 21:14)  1. В функции задержки переменная i только для счетчика и нигде больше не видна и не нужна - так что Для локальных переменных класс памяти static означает, что переменная сохраняется между вызовами функции. Не видна - это когда static применяется к глобальным переменным. Или нет? Однако тут на форуме говорили, что особо свирепый компилятор может так сильно "оптимизировать" подобную программную задержку, что ее совсем не будет (ну вроде как считаем без дела, время тратим, значит выкидываем). И вроде как для программной задержки переменную-счетчик надо объявлять volatile, чтоб оптимизацию над ней подавить...
|
|
|
|
|
Aug 29 2009, 18:47
|

Гуру
     
Группа: Модераторы
Сообщений: 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
|
|
|
|
|
Aug 31 2009, 18:28
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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))
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 31 2009, 18:36
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Student Pupkin @ Aug 30 2009, 00:39)  Для локальных переменных класс памяти static означает, что переменная сохраняется между вызовами функции. Не видна - это когда static применяется к глобальным переменным. Или нет? Для переменных типа static выделяется постоянное место в ОЗУ, точно также, как и для глобальных переменных. И инициализация static начальным значением (очистка, если значение явно не задано) осуществляется точно также, как и у глобальных переменных. Но область видимости переменной типа static действительно ограничена, также, как и у автоматической (локальной) переменной. Тут вы правы.
|
|
|
|
|
Sep 6 2009, 14:41
|
Участник

Группа: Участник
Сообщений: 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 бит вместо десяти ну и обьединение для собственно запихивания байт в целое. Всем спасибо!
Причина редактирования: Уменьшение горизонального размера цитаты.
|
|
|
|
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|