|
STM32 USART и DS18B20, траблы с приемо-передачей байтов |
|
|
|
Aug 19 2011, 19:53
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Пытаюсь завести DS18B20 на STM32(дискавери) по USART. Работу с 1-wire делаю по апптоуту максимаПроблемы начинаются после инициализации, после того как послали 0xF0 получили 0x0E, что значит датчик наместе, далее посылаем 0xCC и т.п не буду повторять код. вот собственно после передачи всех команд начинаем получать биты температуры, но все время нули вылазят. Я думаю что ошибка возможна в OneWireReadByte() хотя хз. OneWireSendByte() формирует из hex -> bin вроде правильно, к примеру 0xCC в двоичной 1100 1100, OneWireSendByte формирует и отсылает 0011 0011, какбы задом наперед, т.е сначала младшие биты слова потом старшие. CODE #include "stm32l1xx.h" #include "PLL/inc/stm32l1xx_gpio.h" #include "PLL/inc/stm32l1xx_usart.h" #include "PLL/inc/stm32l1xx_rcc.h" void Delay_ms(uint32_t ms) { volatile uint32_t nCount; RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq (&RCC_Clocks);
nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms; for (; nCount!=0; nCount--); }
void initPereherial() { GPIO_InitTypeDef GPIO_InitStructure; /* Включаем тактирование */ RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* USART1 Rx (PA10) вход */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART1 Tx (PA9) выход */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Конфигурируем порты PA9, PA10 как альтернативную функцию для USART1 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); }
void UsartInit(int BaudRate) { USART_InitTypeDef USART_InitStructure; /* Настраиваем USART1 */ USART_InitStructure.USART_BaudRate = BaudRate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* Включаем USART1 */ USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); }
volatile uint16_t temp[7];
void OneWireSendByte(uint16_t byte) { for(int i=0; i<8; i++) { if((byte & (1<<i) ) != 0) { USART_SendData(USART1, 0xFF); Delay_ms(1); }else{ USART_SendData(USART1, 0x00); } } }
uint16_t OneWireReadByte() { uint16_t result=0; for(int i=0; i<8; i++) { USART_SendData(USART1, 0xFF); Delay_ms(1); } for(int i=0; i<8; i++) { if(USART_ReceiveData(USART1) != 0xFF) { result |= (1<<i); } } return result; }
int main() { initPereherial(); UsartInit(9800); USART_SendData(USART1, 0xF0);
USART_DeInit(USART1); UsartInit(115200); OneWireSendByte(0xCC); OneWireSendByte(0x44); Delay_ms(750);
USART_DeInit(USART1); UsartInit(9800); USART_SendData(USART1, 0xF0);
USART_DeInit(USART1); UsartInit(115200); OneWireSendByte(0xCC); OneWireSendByte(0xBE);
for(int i=0; i<8; i++) { temp[i] = OneWireReadByte(); } }
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Aug 19 2011, 20:32
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(Flexz @ Aug 20 2011, 00:26)  Загляните внурь функций USART_SendData/USART_ReceiveData Думаю вопросы отпадут. и что я там должен был увидеть чтобы меня осинило, записываем и читаем в\из DR, вы с аппноутом знакомы который указывал в ссылке, или работали с 1-wire по uart?
|
|
|
|
|
Aug 20 2011, 17:06
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(ILYAUL @ Aug 20 2011, 13:29)  А зачем Вы задержки налепили в 1 ms? Зачем они там нужны. Задержка только после команды 0х44. Я писал обмен по USART с этим датчиком , правда для MEGA. У ATMEL есть два Application Note (AVR318 и AVR274 ) для этого случая - где чётко расписанно как осуществлять обмен по USART и приложены коды для С. USART он и в Африке USART , а уж DS тем более про С и говорить нечего. Может поможет. почитаю эти аппы, а про задержку в 1ms, вычитал на какомто форуме что нужно при записи ставить, хотя и без неё все изначально было и также не фурычило
|
|
|
|
|
Aug 20 2011, 19:09
|
Местный
  
Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797

|
Цитата(iPKM @ Aug 20 2011, 00:32)  и что я там должен был увидеть чтобы меня осинило, записываем и читаем в\из DR, вы с аппноутом знакомы который указывал в ссылке, или работали с 1-wire по uart? не читал и не работал. Зато достаточно работал с уартом, что бы видеть что код у вас нерабочий. Перед тем как читать DR надо дождаться того что бы там что-то появилось, а перед тем как писать в него надо дождаться пока из него все будет отправлено (задержки у вас там именно за этим стоят, причем почему то не везде). Аппноуты это конечно здорово, но документацию на контроллер тоже читать надо.
|
|
|
|
|
Aug 21 2011, 09:45
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(Flexz @ Aug 20 2011, 23:09)  не читал и не работал. Зато достаточно работал с уартом, что бы видеть что код у вас нерабочий. Перед тем как читать DR надо дождаться того что бы там что-то появилось, а перед тем как писать в него надо дождаться пока из него все будет отправлено (задержки у вас там именно за этим стоят, причем почему то не везде). Аппноуты это конечно здорово, но документацию на контроллер тоже читать надо. Ожидание освобожнение буфера прописывал не помогает, и ожидание никакое никанает(его там вообще не должно быть) Попробую сегодня сделать обвязку как указано аппноуте на всяк случай, потом уже буду возращаться к коду.
|
|
|
|
|
Aug 21 2011, 10:19
|
Местный
  
Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797

|
Ну дело ваше, конечно, но на вашем месте прежде чем делать что-то посложнее я бы разобрался с простым. А именно с работой с уартом, ибо в коде полная ахинея. Вот это: Код for(int i=0; i<8; i++) { if(USART_ReceiveData(USART1) != 0xFF) { result |= (1<<i); } } не считает 8 байт по уарту, а 8 раз считает одно и тоже значение из регистра DR, нафига оно вам 8 раз? Отправка данных выглядит примерно так (копипаст из семплов) Код USART_SendData(USARTy, data1); /* Loop until USARTy DR register is empty */ while(USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET) { } соответсвенно прием: Код /* Loop until the USARTz Receive Data Register is not empty */ while(USART_GetFlagStatus(USARTz, USART_FLAG_RXNE) == RESET) { }
/* Store the received byte in RxBuffer */ data2 = USART_ReceiveData(USARTz); PS: аппноут, кстати, почитал - интересно, не знал что с 1-wire можно работать через uart
|
|
|
|
|
Aug 21 2011, 12:37
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(Flexz @ Aug 21 2011, 14:19)  Ну дело ваше, конечно, но на вашем месте прежде чем делать что-то посложнее я бы разобрался с простым. А именно с работой с уартом, ибо в коде полная ахинея. Вот это: Код for(int i=0; i<8; i++) { if(USART_ReceiveData(USART1) != 0xFF) { result |= (1<<i); } } да тут ошибка вышла, т.к переписывал код библиотеки с использованием FT232(а там идет работа с буфером), То для STM он должен выглядить так: Код for(int i=0; i<8; i++) { USART_SendData(USART1, 0xFF); while (!(USART1->SR & USART_SR_TXE)) {} // Ждать освобождения буфера. if(USART_ReceiveData(USART1) != 0xFF) { result |= (1<<i); } } но это все равно пока проблемы не рашает. смотрю щас как сие реализовано в АВР, там заметил что прирывания на время запроса температуры запрещаются и еще помелочи что, в общем нужно проверить. Цитата(ILYAUL @ Aug 21 2011, 14:18)  Да кстати , между командами 0х44 + Delay и 0xBE должен быть RESET. И ещё один подводный камень - UDRE Я не нашел в даташите упоминание про UDRE. а 0xF0 как раз таки и есть ресет и приветствие. и между 0х44 и 0xBE он стоять не может
|
|
|
|
|
Aug 21 2011, 12:39
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 25-05-10
Из: Киев
Пользователь №: 57 515

|
В вашем коде я не вижу, где задается временная диаграмма 1Wire. Если можно - покажите. Например прием бита с 1Wire (смотрите рис.14 в даташит Максима): мы даем низкий уровень на более чем 1 мкс (например на 5 мкс), потом ждем например 6 мкс, потом читаем состояние шины, потом ждем >45мкс до следующего бита. Где можно увидеть на какой микросекунде слота происходит семплирование ? Возможно имеется в виду, что отправка 8 раз подряд байта 0xFF в UART на скорости 115200 как раз эквивалентна (после сглаживания фильтром) подаче низкого уровня на время примерно 8,68мкс (то есть master reaq slot), а затем сразу делается считывание, но не вижу, где ожидание 45 мкс до следующего бита. Не проще ли это сделать на GPIO и не занимать UART - GPIO хотя бы можно на любой порт вывести.
|
|
|
|
|
Aug 21 2011, 13:35
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(Schulz_K @ Aug 21 2011, 16:39)  Возможно имеется в виду, что отправка 8 раз подряд байта 0xFF в UART на скорости 115200 как раз эквивалентна (после сглаживания фильтром) подаче низкого уровня на время примерно 8,68мкс (то есть master reaq slot), а затем сразу делается считывание, но не вижу, где ожидание 45 мкс до следующего бита. Не проще ли это сделать на GPIO и не занимать UART - GPIO хотя бы можно на любой порт вывести. Именно так, потому и диаграмма ненужда. Думал просто ногами дрыгать, но хочеться именно с юартом поработать, потому GPIO пока не рассматриваю. щас что-то вообще бредятина, при посылке F0, получаю FF, вроде датчик откликается, но ответ должен быть 0x10 - 0x90, раньшебыл 0x0E но эт нормально. при считывании температуры в DR все время болтается 0x80, это видать мои чудеса монтажа сказываются) не это просто команды перепутал.
|
|
|
|
|
Aug 21 2011, 14:36
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 25-05-10
Из: Киев
Пользователь №: 57 515

|
А сколько в вашем случае времени проходит при чтении после освобождения шины мастером до момента семплирования ? Это время нужно делать максимально возможным (в пределах тех 15мкс, когда можно делать чтение). Помехоустойчивость такой схемы зависит от программы, тем более что у вас фильтры затягивают сигналы, чтобы 8 импульсов UART превращались в один. У меня были случаи, когда DS18B20 на линии длиной 100м часто сбоил, но при добавлении 2-4 мкс во временные диаграммы все начинало работать стабильно.
|
|
|
|
|
Aug 21 2011, 15:58
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
Цитата(ILYAUL @ Aug 21 2011, 18:54)  Это из DS тогда уж не знаю какой у Вас не пудрите мозг), да ресет подается после 44, но не между 0х44 + Delay и 0xBE ( a 0xCC вместо 0xBE ) <- вот так более понятно непоняток не вызывает заметил еще такую странность, когда идет отладка кода на месте чтения битов, товсе время висит значение 0x80, но если поставить брекпоит в любом месте приема данных, то в окне регистров можно наблюдать 0x80, но когда начиеш просто щелкать по ячейки с любым битом юарта то значение регистра все время обновляется: 80, C0, E0, F0, F8, FC, FE, FF и глохнет, причем меняется только один бит в юарте IDLE. Видать что-то с приривыниями, нужно копать туда
Сообщение отредактировал iPKM - Aug 21 2011, 16:02
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|