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

Ostroukhovio

Members
  • Постов

    12
  • Зарегистрирован

  • Посещение

Информация

  • Город
    Москва

Электроника

  • Стаж в электронике
    6-10 лет

Посетители профиля

Блок последних пользователей отключён и не показывается другим пользователям.

Достижения Ostroukhovio

Новичок

Новичок (1/14)

  • 10 постов на форуме
  • Месяц на форуме
  • Преданный
  • Неделя на форуме

Последние значки

0

Репутация

  1. Кстати забыл уточнить. Линии i2c подтянуты через 51к, так как у устройства очень низкое энергопотребление должно быть и из-за этого частота сейчас 50кГц. Сделал очень урезанную инициализацию акселя: uint8_t CTRL_REG1 = 0x47; ACEL_Write(0x20, CTRL_REG1); И прямую проверку на светодиодах читая регистр OUT_Z: if(ACEL_Read(0x2d)>127){ fLED_Driver(1,3,1); }else{ fLED_Driver(1,1,1); } По логике, вращая плату, в какой-то момент должно происходите переключение светодиодов в одну сторону и соответственно обратно при обратном повороте. Но у меня судя по коду регистр всегда возвращает значение меньше 127. Можно сделать вывод, если я не ошибаюсь, что даже запись регистра запуска CTRL_REG1 не происходит, раз аксель молчит. Сейчас I2C реализовано вот так: uint8_t ACEL_Write(uint8_t addr, uint8_t data){ I2C_Start(I2C_device_w); I2C_Write(addr); I2C_Write(data); I2C_Stop(); } uint8_t ACEL_Read(uint8_t addr){ uint8_t InData; I2C_Start(I2C_device_w); I2C_Write(addr); I2C_Repeated_Start(I2C_device_r); InData = I2C_Read_Ack(); //I2C_Read_Nack(); I2C_Stop(); return InData; } uint8_t I2C_Start(char write_address)/* I2C start function */ { uint8_t status; /* Declare variable */ TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate START */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ TWDR=write_address; /* Write SLA+W in TWI data register */ TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI & clear interrupt flag */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ } uint8_t I2C_Repeated_Start(char read_address) /* I2C repeated start function */ { uint8_t status; /* Declare variable */ //TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT);/* Enable TWI, generate start */ //while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ /* Return 0 for repeated start condition fail */ TWDR=read_address; /* Write SLA+R in TWI data register */ TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ } uint8_t I2C_Write(char data) /* I2C write function */ { uint8_t status; /* Declare variable */ TWDR=data; /* Copy data in TWI data register */ TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ } char I2C_Read_Ack(void) /* I2C read ack function */ { TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA); /* Enable TWI, generation of ack */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ return TWDR; /* Return received data */ } char I2C_Read_Nack(void) /* I2C read nack function */ { TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */ while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */ return TWDR; /* Return received data */ } void I2C_Stop(void) /* I2C stop function */ { TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN);/* Enable TWI, generate stop */ while(TWCR&(1<<TWSTO)); /* Wait until stop condition execution */ }
  2. Да вот и не понятно. Читать та он читает. А вот правильно ли вообще написан код на WRITE в чип - не факт. Так как уже перекрутил кучу конфигов (в том числе и из аппликейшена даташита), аксель не выдает ничего. Самый последний код настройки акселя, я уже без понятия что ему нужно. uint8_t CTRL_REG1 = 0xC7; ACEL_Write(0x20, CTRL_REG1); uint8_t CTRL_REG2 = 0x04; ACEL_Write(0x21, CTRL_REG2); uint8_t CTRL_REG3 = 0x01; ACEL_Write(0x22, CTRL_REG3); uint8_t FF_WU_THS_1 = 0x01; ACEL_Write(0x32, FF_WU_THS_1); uint8_t FF_WU_DURATION_1 = 0x00; ACEL_Write(0x33, FF_WU_DURATION_1); //read HP_FILTER_RESET register ACEL_Read(0x23); uint8_t FF_WU_CFG_1 = 0x6A; ACEL_Write(0x30, FF_WU_CFG_1);
  3. Шью устройство в ожидании что по двойному клику аксель начнет будить МК) Учитывая что прерывания точно в МК работают корректно (проверено), выложил именно фрагменты в которых сомневаюсь.
  4. Сложность в том, что по сути сошлись несколько неизвестных: четкость пайки чипа, правильность работы с I2C и правильность настройки акселя. В условиях ультракомпактности устройства, проверить работоспособность я могу либо выводя некие флаги на светодиоды, либо смотря, просыпается ли устройство и работает штатно. Собственно поэтому и прошу помощи в заведомо рабочем коде.
  5. Всем доброго дня. Помогите пожалуйста с акселем LIS302DL. Пишу в AVR Studio. Нацарапал инициализацию и функции работы с I2C, регистр имени читает и возвращает 0x3b как положено. Пробую записывать регистры чипа, но результата не вижу. Задача заключается в том, чтобы по двойному клику (а в идеале, еще и по определенному перевороту акселя) выводить прерывания на ножки INT0 и\или INT1 акселя, с целью пробуждения МК. После запуска, МК полностью настраивается, настраивает аксель и засыпает. В настоящий момент, для упрощения отслеживания наличия изменений на ноге МК, я не завожу его в сон, а просто вывожу состояние на светодиод. Помогите пожалуйста с кодом. Мой фрагмент кода: Инициализация I2C, настройка акселя и выключение I2C в Main() : #define F_CPU 8000000UL #define F_I2C 50000UL #define TWBR_VALUE (((F_CPU)/(F_I2C)-16)/2) #if ((TWBR_VALUE > 255) || (TWBR_VALUE == 0)) #error "TWBR value is not correct" #endif #define I2C_device 0b0011101 I2C_Config(1); ACEL_Config(); I2C_Config(0); Функция инициализации I2C: void I2C_Config(uint8_t Mode){ if(Mode){ TWBR = TWBR_VALUE; TWSR = 0; }else{ TWCR = 0; } } Функция настройки акселя: void ACEL_Config(void){ unsigned int i = 0; uint8_t CTRL_REG1 = 0b01000111; I2C_Work(0x20, CTRL_REG1, 0); uint8_t FF_WU_CFG_1 = 0b01110000; I2C_Work(0x30, FF_WU_CFG_1, 0); /* Настроить регистр управления прерываниями: включить Click interrupt1 */ uint8_t CTRL_REG3 = 0b00111111; I2C_Work(0x22, CTRL_REG3, 0); /* Включить генерацию прерывания по двойному клику по оси Z */ uint8_t CLICK_CFG = 0b01100000; I2C_Work(0x38, CLICK_CFG, 0); uint8_t CLICK_THSXY = 0xAA; I2C_Work(0x3B, CLICK_THSXY, 0); uint8_t CLICK_THSZ = 0x0A; I2C_Work(0x3C, CLICK_THSZ, 0); /* настройка лимита времени */ uint8_t CLICK_TimeLimit = 127; I2C_Work(0x3D, CLICK_TimeLimit, 0); /* настройка задержки */ uint8_t CLICK_Latency = 127; I2C_Work(0x3E, CLICK_Latency, 0); /* настройка окна выборки */ uint8_t CLICK_Window = 255; I2C_Work(0x3F, CLICK_Window, 0); //uint8_t CLICK_SRC = 0b01101010; //I2C_Work(0x39, CLICK_SRC, 0); } Функции работы с I2C: void I2C_Start(void){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); } void I2C_Stop(void){ TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); } uint8_t I2C_Work(uint8_t adr, uint8_t data, uint8_t setaddr){ uint8_t getdata; I2C_Start(); /*выдаемна шину пакет SLA-W*/ TWDR = (I2C_device<<1)|0; TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); /*передаем адрес регистра*/ TWDR = adr; TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); /*передаем данные или пропускаем*/ if (!setaddr){ /*это чтобы привести данные к BCD формату*/ //data = ((data/10)<<4) + data%10; TWDR = data; TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); }else{ /*выдаем на шину пакет SLA-R*/ TWDR = (I2C_device<<1)|1; TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); /*считываем данные*/ TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); getdata = TWDR; } /*формируем состояние СТОП*/ I2C_Stop(); return getdata; } uint8_t I2C_Read(void){ uint8_t data; I2C_Start(); /*выдаем на шину пакет SLA-R*/ TWDR = (I2C_device<<1)|1; TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); /*считываем данные*/ TWCR = (1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); data = TWDR; /*формируем состояние СТОП*/ I2C_Stop(); return data; }
  6. Все разрешилось, считыватель ждал от меня ответа перед началом трансляции ID: RFID.h #ifndef RFID_H #define RFID_H #include <xc.h> #define RFID_tris TRISC7 #define RFID_port RC7 #define RFID_lat LATC7 #define _XTAL_FREQ 40000000 unsigned char RFID_id[8]; char RFID_ready; void RFID_config(void); char RFID_reset(void); void RFID_write(unsigned char Byte, char Power); void RFID_write_bit(char Bit); unsigned char RFID_read(void); char RFID_read_bit(void); void RFID_scan(char Power); #endif /* RFID_H */ RFID.c #include "RFID.h" void Interrupts(char Mode){ INTCONbits.GIE = Mode; INTCONbits.PEIE = Mode; } void RFID_config(void){ RFID_lat = 0; RFID_tris = 1; RFID_ready = 0; } char RFID_reset(void){ char Response; char Retries = 125; Interrupts(0); RFID_lat = 0; RFID_tris = 1; Interrupts(1); // wait until the wire is high... just in case do{ if(--Retries == 0) return 0; __delay_us(2); }while(!RFID_port); Interrupts(0); RFID_lat = 0; RFID_tris = 0; Interrupts(1); __delay_us(480); Interrupts(0); RFID_tris = 1; __delay_us(70); Response = !RFID_port; Interrupts(1); __delay_us(410); return Response; } void RFID_write(unsigned char Byte, char Power){ unsigned char bitMask; for(bitMask = 0x01; bitMask; bitMask <<= 1){ RFID_write_bit((bitMask & Byte)?1:0); } if (!Power) { Interrupts(0); RFID_tris = 1; RFID_lat = 0; Interrupts(1); } } void RFID_write_bit(char Bit){ Interrupts(0); RFID_lat = 0; RFID_tris = 0; if(Bit){ __delay_us(10); RFID_lat = 1; Interrupts(1); __delay_us(55); } else { __delay_us(65); RFID_lat = 1; Interrupts(1); __delay_us(5); } } unsigned char RFID_read(void){ unsigned char bitMask; unsigned char Byte = 0; for (bitMask = 0x01; bitMask; bitMask <<= 1){ if(RFID_read_bit()) Byte |= bitMask; } return Byte; } char RFID_read_bit(void){ char Bit; Interrupts(0); RFID_tris = 0; RFID_lat = 0; __delay_us(3); RFID_tris = 1; __delay_us(10); Bit = RFID_port; Interrupts(1); __delay_us(53); LATA3 = Bit; return Bit; } void RFID_scan(char Power){ if(RFID_reset()){ // Если карта приложена RFID_ready = 0; RFID_write(0x33, Power); // вернуть ридеру команду на чтение байт int i; for(i = 0; i < 8; i++) { RFID_id[i] = RFID_read(); // здесь искомые стартовый байт, 6 байт данных и crc } RFID_ready = 1; } } Main.c //Предварительная конфигурация RFID_config(); INTCONbits.GIE = 1; INTCONbits.PEIE = 1; //Полученный от считывателя ID-карты ключа записывается в массив RFID_id[8]. //RFID_ready - флаг устанавливаемый моей библиотекой при прочтении очередного ID ключа-карты. //После обработки полученного ID карты-ключа, необходимо сбросить данный флаг иначе библиотека не продолжит работу со считывателем. while(1){ if(!RFID_ready) RFID_scan(0); } Всем спасибо и удачи!
  7. #define F_CPU 40000000 int RF_ID[16]; void main(void){ SYSTEM_Initialize(); UART_Config(9600); IO_Config(1); INTCONbits.GIE = 1; INTCONbits.PEIE = 1; while(1){ if(PIE1bits.RC1IE == 1 && PIR1bits.RC1IF == 1){ int i; for(i = 0; i < 8; i++){ RF_ID[i] = USART_RxChar(); } } } } void IO_Config(char Mode){ TRISA = 0; TRISB = 0; TRISC = 0; //Отключение АЦП PCFG0 = 0; PCFG1 = 0; PCFG2 = 0; PCFG3 = 0; VNCFG = 0; ADCON1 = 0x0;//0x07; /*Светодиоды*/ kLED_tris = 0; kLED_lat = 0; /*Звук*/ kSOUND_tris = 0; kSOUND_lat = 0; /*Замок*/ kLOCK_tris = 0; kLOCK_lat = 0; /*Защитный датчик*/ iGUARD_tris = 1; iGUARD_lat = 0; /*RFID*/ iRFID_tris = 1; iRFID_lat = 0; /*Геркон*/ iGER_tris = 1; iGER_lat = 0; /*Сброс Ethernet (инверсно)*/ kETHRES_tris = 0; kETHRES_lat = 0; } void UART_Config(long baud_rate){ float bps; bps = (( (float) (F_CPU) / (64 * (float) baud_rate)) - 1); SPBRG1 = (int)bps; TXSTA1bits.CSRC = 0; TXSTA1bits.TX9 = 0; TXSTA1bits.TXEN = 0; TXSTA1bits.SYNC = 0; TXSTA1bits.BRGH = 0; BAUDCON1bits.BRG16 = 0; RCSTA1 = 0x90; PIR1bits.RCIF = 0; PIE1bits.RCIE = 1; } int USART_RxChar(void){ while(PIR1bits.RC1IF == 0); NOP(); if(RCSTAbits.OERR){ RCSTAbits.CREN = 0; NOP(); RCSTAbits.CREN = 1; } int DATA; DATA = RCREG1; PIR1bits.RC1IF = 0; return DATA; } Выдержки из моего тестового кода.
  8. До этого изделие работало на 328 меге, данный PIC применили так как требуется CAN. Отладку ловлю в данный момент именно с CAN-USB переходника. То что UART работает везде идентично это и ежу понятно, по этому и непонятки, где мои данные)
  9. Я так понимаю, если делать 1 wire на своей функции обработки, учитывая что считыватель в отличае от прочих микросхем никого не спрашивая сразу выплевывает ID карточки, нужно вылавливать в цикле while первое изменение состояние на ножке МК и далее по таймингам прям писать в массив биты формируя байты?
  10. На AVR именно на приемнике UART и катаем считыватели. Хочу пересадить изделие на свой родной PIC, но какаято ерунда: считыватель должен на протоколе 1990а отдать стартовый байт, 6 байт ключа и проверочный байт, но по факту при крикладывании карты я получаю всего один байт, то есть прерывание срабатывает всего один раз. Проверка байт осуществляется по штатному ряду светодиодов WS2812, загорается всего один вместо 8 или 12 шт. Для общего развития был бы рад изучить такой вариант
  11. С этими считывателями уже работали на АВР просто. А UART потому-что он просто напросто уже применен при разводке платы. Используем провод считывателя на входе RX (ножка RC7) контроллера. Да и таблеток под рукой нет, только CP-Z и ключ-карточка доступа. Сам по себе юарт настроился так как при прикладывании карточки к считывателю я явно вижу уход в прерывание по светодиоду сервисному и звукоизлучателю на моей плате, проблема именно как на этом PIC правильно организовать обработку 12 последовательных байт ID ключа.
  12. Народ подскажите пожалуйста примерчик настройки и работы с приемником контроллера UART1. Нужно со считывателя карт доступа CP-Z-2 по протоколу 1990а получать массив байт. Уже всю голову сломал, либо не получаю ничего, либо все байты 255.
×
×
  • Создать...