Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » CERGEI » 1-wire driver(usart+dma)


1-wire driver(usart+dma)

Сообщений 1 страница 2 из 2

1

stm32f103c8t6
Настраивал вывод PA9 как альтернативная функция open drain
Применение usart1+dma

1wire.h

Код:
#ifndef _1WIRE_H
#define _1WIRE_H 

#include "stm32f1xx.h"

#define OW_SEND_RESET    1
#define OW_NO_RESET    2

#define OW_OK    	1
#define OW_ERROR    2
#define OW_NO_DEVICE	3

#define OW_NO_READ    0xff

#define OW_READ_SLOT	0xff

#define APB1CLK  72000000UL
#define  BAUD       115200UL
#define  BAUD2       9600UL

void OW_Init(void);
uint8_t OW_Reset(void);
uint8_t OW_Send(uint8_t sendReset, char *command, uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart);
char DLcrc8 (uint8_t *pData,char counterBytes );

#endif //1WIRE_H


1wire.c

Код:
#include "1wire.h"

// Буфер для приема/передачи по 1-wire
uint8_t ow_buf[8];

#define OW_0	0x00
#define OW_1	0xff
#define OW_R_1	0xff

//-----------------------------------------------------------------------------
// функция преобразует один байт в восемь, для передачи через USART
// ow_byte - байт, который надо преобразовать
// ow_bits - ссылка на буфер, размером не менее 8 байт
//-----------------------------------------------------------------------------
void OW_toBits(uint8_t ow_byte, uint8_t *ow_bits) {
	uint8_t i;
	for (i = 0; i < 8; i++) {
    if (ow_byte & 0x01) {
    	*ow_bits = OW_1;
    } else {
    	*ow_bits = OW_0;
    }
    ow_bits++;
    ow_byte = ow_byte >> 1;
	}
}

//-----------------------------------------------------------------------------
// обратное преобразование - из того, что получено через USART опять собирается байт
// ow_bits - ссылка на буфер, размером не менее 8 байт
//-----------------------------------------------------------------------------
uint8_t OW_toByte(uint8_t *ow_bits) {
	uint8_t ow_byte, i;
	ow_byte = 0;
	for (i = 0; i < 8; i++) {
    ow_byte = ow_byte >> 1;
    if (*ow_bits == OW_R_1) {
    	ow_byte |= 0x80;
    }
    ow_bits++;
	}

	return ow_byte;
}






//-----------------------------------------------------------------------------
// инициализиция USART и DMA
//-----------------------------------------------------------------------------
void OW_Init(void)
    {
    	//тактирование usart1 от шины PLC1 с частатой шины 72 Мгц
    	
    	RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
    	RCC->APB2ENR|=RCC_APB2ENR_USART1EN;
    	RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;
    	
    	GPIOA->CRH&= ~(GPIO_CRH_MODE9);
    	GPIOA->CRH|=GPIO_CRH_MODE9_0|GPIO_CRH_MODE9_1;
    	GPIOA->CRH&= ~(GPIO_CRH_CNF9);
    	GPIOA->CRH|= GPIO_CRH_CNF9_0|GPIO_CRH_CNF9_1;
    	
    	USART1->BRR =(APB1CLK+BAUD/2)/BAUD;  // 115200
            USART1->CR1 |= USART_CR1_TE |USART_CR1_RE; // 
    	USART1->CR3 |=USART_CR3_HDSEL;

    	
    	RCC->AHBENR |=RCC_AHBENR_DMA1EN;       //
    	DMA1_Channel5->CPAR = (uint32_t) &(USART1->DR);
    	DMA1_Channel5->CMAR = (uint32_t) ow_buf;        //
    	DMA1_Channel5->CNDTR = 0x08;                //

    	DMA1_Channel5->CCR=0;
    	DMA1_Channel5->CCR  = 
                         
                        	DMA_CCR_MINC//DMA_CCR5_MINC
                        	//DMA_CCR_CIRC|
                        	//DMA_CCR_DIR
                          ;
    
    	DMA1_Channel4->CPAR = (uint32_t)&(USART1->DR);
    	DMA1_Channel4->CMAR = (uint32_t) ow_buf;        //
    	DMA1_Channel4->CNDTR = 0x08;                //

    	DMA1_Channel4->CCR=0;
    	DMA1_Channel4->CCR  = 
                        	 
                        	DMA_CCR_MINC|//DMA_CCR6_MINC|
                        	//DMA_CCR_CIRC|
                        	DMA_CCR_DIR//DMA_CCR6_DIR
                        	 ;
                        	
    }
//-----------------------------------------------------------------------------
// осуществляет сброс и проверку на наличие устройств на шине
//-----------------------------------------------------------------------------    
	uint8_t OW_Reset() {
	uint8_t ow_presence;
    
    USART1->CR1 &= ~USART_CR1_UE; //   USART1  	
    USART1->BRR =(APB1CLK+BAUD2/2)/BAUD2; //usart1 9600
    
    USART1->CR1 |= USART_CR1_UE; //   USART1  
    	
    	
    //USART1->ICR|=USART_ICR_TCCF;
    USART1->SR|=USART_SR_TC;
    USART1->DR= 0xf0;
    
    	
     while(!(USART1->SR & USART_SR_TC));
    ow_presence = USART1->DR;
    	
    	
    USART1->CR1 &= ~USART_CR1_UE; //   USART1  	
    USART1->BRR =(APB1CLK+BAUD/2)/BAUD; //usart1  115200
    USART1->CR1 |= USART_CR1_UE; //   USART1  	
	
	if (ow_presence != 0xf0) {
    return OW_OK;
	  }

	return OW_NO_DEVICE;
   }
	
	 
	 
//-----------------------------------------------------------------------------
// процедура общения с шиной 1-wire
// sendReset - посылать RESET в начале общения.
//     OW_SEND_RESET или OW_NO_RESET
// command - массив байт, отсылаемых в шину. Если нужно чтение - отправляем OW_READ_SLOTH
// cLen - длина буфера команд, столько байт отошлется в шину
// data - если требуется чтение, то ссылка на буфер для чтения
// dLen - длина буфера для чтения. Прочитается не более этой длины
// readStart - с какого символа передачи начинать чтение (нумеруются с 0)
//    можно указать OW_NO_READ, тогда можно не задавать data и dLen
//-----------------------------------------------------------------------------
//OW_Send(OW_SEND_RESET, "\xcc\xbe\xff\xff", 4,  buf, 2, 2);	 
uint8_t OW_Send(uint8_t sendReset, char *command, uint8_t cLen,
    uint8_t *data, uint8_t dLen, uint8_t readStart) {

	
	if (sendReset == OW_SEND_RESET) {
    if (OW_Reset() == OW_NO_DEVICE) {
    	return OW_NO_DEVICE;
    }
	}

	while (cLen > 0) {

    OW_toBits(*command, ow_buf);
    command++;
    cLen--;

    USART1->CR1 |= USART_CR1_UE; //   USART1
    DMA1_Channel5->CNDTR = 0x08; 
    DMA1_Channel4->CNDTR = 0x08; 
    
    DMA1_Channel5->CCR  |=  DMA_CCR_EN; //DMA_CCR5_EN; 
    DMA1_Channel4->CCR  |=  DMA_CCR_EN; //DMA_CCR4_EN;   
    USART1->CR3|=USART_CR3_DMAR | USART_CR3_DMAT;
    
	
    while(!(DMA1->ISR & DMA_ISR_TCIF5)){};
    DMA1->IFCR |= DMA_IFCR_CTCIF5;   // прием завершен
    
    DMA1_Channel5->CCR  &=  ~DMA_CCR_EN; //DMA_CCR5_EN; 
    DMA1_Channel4->CCR  &=  ~DMA_CCR_EN; //DMA_CCR4_EN;  
        	
    USART1->CR3&= ~(USART_CR3_DMAR | USART_CR3_DMAT);
    USART1->CR1 &= ~USART_CR1_UE; //   USART1

    // 
    if (readStart == 0 && dLen > 0) {
    	*data = OW_toByte(ow_buf);
    	data++;
    	dLen--;
    } else {
    	if (readStart != OW_NO_READ) {
        readStart--;
    	}
    }
	}

	return OW_OK;
}
    
char DLcrc8 (uint8_t *pData,char counterBytes )
 { 
     char  crc;
     char  data;
     char i,fb;

     crc =0;                        // Инициализируем
   do                                       // Просматриваем весь массив
    { 
       data = *pData++;                     // Читаем байт
       for (i=0;i<8;i++)               // счетчик битов в байте
        {
            fb =crc  ^ data;                  //восемь бит,начинаем с конца с перевнутым полиномом
            fb&=1;                        // 100110001,то есть будет 100011001,смотрим на младший бит
            crc >>= 1;                       //если с датой обои 
            data >>=1;
            if (fb == 1)crc^=0x8c;// полином, мля 1000 1100
        }
    }
   while (counterBytes-- );
   return crc;
}
 


Подсчет crc и выдача если что то с датчиком. Правда вот может быть равен crc нулю ? потому что usart не запускается,пока не будет перепада на входе PA9 и потому будет crc по нулям crc и buf. Ошибку не показывает потому.
Пример программы main :

Код:

    char temp,temp1;
	 uint8_t buf[10];
	char txt[10];
  uint8_t CRC_ds,error_ds,i;

    OW_Send(OW_SEND_RESET, "\xcc\xbe\xff\xff\xff\xff\xff\xff\xff\xff\xff", 11,  buf, 11, 2) ;//2);
    	 CRC_ds=DLcrc8(buf,7);         //функция вычисления контрольной суммы
   if(CRC_ds==buf[8]&&!(CRC_ds==0)) 
      error_ds=1;   //сравниваем теперь и если норм то возращается единичка
   else
     error_ds=0;
	 
	 if(error_ds)
	 {
    	temp = ( ((buf[1]&0x07)<<4)|(buf[0]>>4));
    	temp1=(buf[0]&0x0F);	
    	temp1=((temp1<<1)+(temp1<<3));	
    	temp1=(temp1>>4);	
    	sprintf(txt," T=%d.%d C  ",temp,temp1);
    	ssd1306_Puts(txt,1);  // text and stroka
    	ssd1306_update(1);
	 }
	 else
	 {
    	sprintf(txt," T=Error   ");
    	ssd1306_Puts(txt,1);  // text and stroka
    	ssd1306_update(1);
	 }
	 for(i=0;i<9;i++)
	    buf[i]=0;
	 
	 CRC_ds=0;
    OW_Send(OW_SEND_RESET, "\xcc\x44", 2,  NULL,  NULL,  OW_NO_READ);
    
    osDelay(1000);

Отредактировано CERGEI (2017-04-06 08:02:02)

2

Поправил по ходу работы.


Вы здесь » Микроконтроллеры » CERGEI » 1-wire driver(usart+dma)