在网上参考了两个人的思想原理后动工,3天内搞定!其实也就是ds2408的工作原理,参考文献列出如下:
在STM32上通过UART+DMA实现One-Wire总线
http://www.stmcu.org/module/forum/thread-581885-1-1.html
http://wenku.baidu.com/link?url=aJy-AA_isWC-JtFKPAz58Gq3avNilMHlcRkRY3WK-cSDvqXB-CRuR_VSzNF6zYIr7ZMEPA4ifpwSef2J9SXpT1wVN_FA3Ak0udloV4JpByO
主要参考了第一个文献,第二个文献作为原理说明。
贴出代码前有问题要说明一下,就是其实第三天最后的时间就浪费在一个很小的细节上,就是温度转换时间在12位时为750ms,如果发出温度转换命令后立马去读取暂存器是读不出正确温度,
第三条的晚上差点就犯了这错误,几乎就要放弃了。已经都寻找到了替代方案,就是TC1047+ADC的方式,可是后来一想又心有不甘,明明原理上是对的,怎么就出不来呢!所以恒心在这里还是很重要的,一瞬间,一想到这点,随便改了两下代码,把发出温度转换命令后再读取温度前加了个延时就搞定了!
很抱歉代码从keil v5中贴出来是中文注释全部都乱码了,先不管它,以后养成英语注释的习惯,顺便解决下keil 对中文支持不好的问题。
下面是主代码DS18B20.c
#include "ds18b20.h"
#include <stdio.h>
#include "led.h"
u8 dmabuffer[8]={1,2,3,4,5,6,7,8};
bool DS18B20_Rst(void)
{
u8 revdat;
uart3_init(36,9600);
while(USART3->SR&(1<<5)) USART3->SR&=0xffff-1<<5;
USART3->SR&=0xff-(1<<6);
USART3->SR&=0xff-(1<<5);
USART3->CR1|=1<<2;//?óê?ê1?ü
USART3->CR1|=1<<3;//·¢?íê1?ü
USART3->SR&=0xff-(1<<6);
USART3->DR=0xf0;
while((USART3->SR&0X40)==0);//μè′y·¢?ííê3é
USART3->SR&=0xffff-(1<<6);
while(USART3->SR&(1<<5)==0);//μè′y?óê?±ê????1
revdat=USART3->DR&0xff;
//printf("%x",revdat);
uart3_init(36,115200);
return revdat!=0xf0;
}
void bytetobit(u8 byte,u8* bits )
{
u8 j;
for (j=0;j<8;j++)
{
if(byte&(1<<j)) *bits=0xff;
else *bits=0x00;
bits++;
}
}
u8 bitstobyte(u8* bits)
{
u8 i;
u8 byte=0;
for(i=0;i<8;i++)
{
if(*bits==0xff) byte|= (1<<i);//μí???ú?°
bits++;
}
return byte;
}
u16 j=0;
void dma_transffer()
{
USART3->SR&=0xff-(1<<6);
USART3->SR&=0xff-(1<<5);
USART3->CR3|=1<<6;//ê1?üDMA?óê?
USART3->CR3|=1<<7;//ê1?üDMA·¢?í
USART3->CR1|=1<<2;//?óê?ê1?ü
USART3->CR1|=1<<3;//·¢?íê1?ü
DMA1->IFCR|=1<<4;
DMA1->IFCR|=1<<8;
MYDMA_Enable(DMA1_Channel2);
MYDMA_Enable(DMA1_Channel3);
while((DMA1->ISR & 1<<5) ==0);//μè′yDMA?óê?íê3é
DMA1_Channel2->CCR&=~(1<<0); //1?±?DMA
DMA1_Channel3->CCR&=~(1<<0);
// printf("%d",DMA1_Channel2->CNDTR);
USART3->CR3&=0xff-1<<6;//1?±?uart dmaí¨μà
USART3->CR3&=0xff-1<<7;
//for (j=0;j<8;j++)
//printf("%d",dmabuffer[j]);
}
//D′ò???×??úμ?DS18B20
//dat£oòaD′è?μ?×??ú
void writebyte(u8 dat)
{
bytetobit(dat,dmabuffer);
dma_transffer();
}
void Write_Buffer(u8* buf,u8 length)
{
while(length--)
{
writebyte(*buf);
buf++;
}
}
u8 readbyte()
{
bytetobit(0xff,dmabuffer );
dma_transffer();
return bitstobyte(dmabuffer);
}
void Read_Buffer(u8* buf,u8 length)
{
while(length--)
{
*buf=readbyte();
buf++;
}
}
//′óds18b20μ?μ????è?μ
//???è£o0.1C
//·μ???μ£o???è?μ £¨-550~1250£?
short DS18B20_Get_Temp(void)
{
u8 temp;
u8 TL,TH;
short tem;
DS18B20_Rst();
Write_Buffer("\xCC\x44",2); // ds1820 start convert
delay_ms(500);
DS18B20_Rst();
Write_Buffer("\xCC\xbe",2); // ds1820 read data
TL=readbyte(); // LSB
TH=readbyte(); // MSB
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0;//???è?a?o
}else temp=1;//???è?a?y
tem=TH; //??μ???°???
tem<<=8;
tem+=TL;//??μ?μ×°???
tem= tem>>6;//×a??*0.0625?íê?3yó?16?àμ±óúóòò?4?? 2??ao?1ê???èéy??á?4±?
if(temp)return tem; //·μ?????è?μ
else return -tem;
}
下面随便也把一些外设驱动代码贴出来,主要是串口配置和DMA配置的
#include "sys.h"
#include "usart.h"
//V1.3DT???μ?÷
//?§3?êêó|2?í??μ?ê??μ?′??ú2¨ì??êéè??.
//?óè?á???printfμ??§3?
//???óá?′??ú?óê??üá?1|?ü.
//DT?yá?printfμúò???×?·??aê§μ?bug
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//?óè?ò???′ú??,?§3?printfoˉêy,??2?Dèòa????use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//±ê×??aDèòaμ??§3?oˉêy
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef?ˉ d in stdio.h. */
FILE __stdout;
//?¨ò?_sys_exit()ò?±ü?aê1ó?°??÷?ú?£ê?
_sys_exit(int x)
{
x = x;
}
//???¨ò?fputcoˉêy
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//?-?··¢?í,?±μ?·¢?ííê±?
USART1->DR = (u8) ch;
return ch;
}
#endif
//end
//////////////////////////////////////////////////////////////////
#ifdef EN_USART1_RX
u8 USART_RX_BUF[64];
u8 USART_RX_STA=0;
void USART1_IRQHandler(void)
{
u8 res;
if(USART1->SR&(1<<5))//?????
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0)//?????
{
if(USART_RX_STA&0x40)//????0x0d
{
if(res!=0x0a)USART_RX_STA=0;//????,????
else USART_RX_STA|=0x80; //?????
}else //????0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)USART_RX_STA=0;//??????,??????
}
}
}
}
}
#endif
#ifdef EN_USART3_RX //è?1?ê1?üá??óê?
//′??ú1?D??·t??3ìDò
//×¢òa,?áè?USARTx->SR?ü±ü?a?a??????μ?′í?ó
u8 USART_RX_BUF[64]; //?óê??o3?,×?′ó64??×??ú.
//?óê?×′ì?
//bit7£??óê?íê3é±ê??
//bit6£??óê?μ?0x0d
//bit5~0£??óê?μ?μ?óDD§×??úêy??
u8 USART_RX_STA=0; //?óê?×′ì?±ê??
void USART3_IRQHandler(void)
{
u8 res;
if(USART3->SR&(1<<5))//?óê?μ?êy?Y
{
res=USART3->DR;
if((USART_RX_STA&0x80)==0)//?óê??′íê3é
{
if(USART_RX_STA&0x40)//?óê?μ?á?0x0d
{
if(res!=0x0a)USART_RX_STA=0;//?óê?′í?ó,??D??aê?
else USART_RX_STA|=0x80; //?óê?íê3éá?
}else //?1??ê?μ?0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)USART_RX_STA=0;//?óê?êy?Y′í?ó,??D??aê??óê?
}
}
}
}
}
#endif
//3?ê??ˉIO ′??ú1
//pclk2:PCLK2ê±?ó?μ?ê(Mhz)
//bound:2¨ì??ê
//CHECK OK
//091209
void uart3_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//μ?μ?USARTDIV
mantissa=temp; //μ?μ???êy2?·?
fraction=(temp-mantissa)*16; //μ?μ?D?êy2?·?
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<3; //ê1?üPORTB?úê±?ó
RCC->APB1ENR|=1<<18; //ê1?ü′??ú3ê±?ó
GPIOB->CRH=0X44444f44;//IO×′ì?éè??
// GPIOB->CRH&=0XFFFF00FF;
// GPIOB->CRH|=0X00004b00;
RCC->APB1RSTR|=1<<18; //?′??′??ú3
RCC->APB1RSTR&=~(1<<18);//í£?1?′??
//2¨ì??êéè??
USART3->BRR=mantissa; // 2¨ì??êéè??
USART3->CR1|=0X200C; //1??í£?1,?TD£?é??.
#ifdef EN_USART3_RX //è?1?ê1?üá??óê?
//ê1?ü?óê??D??
USART3->CR1|=1<<8; //PE?D??ê1?ü
USART3->CR1|=1<<5; //?óê??o3???·????D??ê1?ü
MY_NVIC_Init(3,3,USART3_IRQChannel,2);//×é2£?×?μíó??è??
#endif
}
void uart1_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//??USARTDIV
mantissa=temp; //??????
fraction=(temp-mantissa)*16; //??????
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //??PORTA???
RCC->APB2ENR|=1<<14; //??????
GPIOA->CRH=0X444444B4;//IO????
RCC->APB2RSTR|=1<<14; //????1
RCC->APB2RSTR&=~(1<<14);//????
//?????
USART1->BRR=mantissa; // ?????
USART1->CR1|=0X200C; //1???,????.
#ifdef EN_USART1_RX //???????
//??????
USART1->CR1|=1<<8; //PE????
USART1->CR1|=1<<5; //???????????
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//?2,?????
#endif
}
#include "dma.h"
u16 DMA1_MEM_LEN;//±£′?DMA??′?êy?Y′??íμ?3¤?è
//DMA1μ??÷í¨μà????
//?aà?μ?′?ê?D?ê?ê?1ì?¨μ?,?aμ?òa?ù?Y2?í?μ??é??à′DT??
//′ó′?′¢?÷->íaéè?£ê?/8??êy?Y?í?è/′?′¢?÷??á??£ê?
//DMA_CHx:DMAí¨μàCHx
//cpar:íaéèμ??·
//cmar:′?′¢?÷μ??·
//cndtr:êy?Y′?ê?á?
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr,bool dir)
{
RCC->AHBENR|=1<<0;//?a??DMA1ê±?ó
__nop();
__nop();
__nop();
while(DMA_CHx->CCR&0X01) ; //1?±?DMA;//μè′yDMA?é????
DMA_CHx->CPAR=cpar; //DMA1 íaéèμ??·
DMA_CHx->CMAR=(u32)cmar; //DMA1,′?′¢?÷μ??·
DMA1_MEM_LEN=cndtr; //±£′?DMA′?ê?êy?Yá?
DMA_CHx->CNDTR=cndtr; //DMA1,′?ê?êy?Yá?
DMA_CHx->CCR=0X00000000;//?′??
if(dir) DMA_CHx->CCR|=1<<4; //′ó′?′¢?÷?á
else DMA_CHx->CCR&=0xffff-1<<4;
DMA_CHx->CCR|=0<<5; //??í¨?£ê?
DMA_CHx->CCR|=0<<6; //íaéèμ??··???á??£ê?
DMA_CHx->CCR|=1<<7; //′?′¢?÷??á??£ê?
DMA_CHx->CCR|=0<<8; //íaéèêy?Y?í?è?a8??
DMA_CHx->CCR|=0<<10; //′?′¢?÷êy?Y?í?è8??
DMA_CHx->CCR|=1<<12; //?Dμèó??è??
DMA_CHx->CCR|=0<<14; //·?′?′¢?÷μ?′?′¢?÷?£ê?
}
//?a??ò?′?DMA′?ê?
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_CHx->CCR&=~(1<<0); //1?±?DMA′?ê?
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,′?ê?êy?Yá?
DMA_CHx->CCR|=1<<0; //?a??DMA′?ê?
}
主程序如下
#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdg.h"
#include "timer.h"
#include "lcd.h"
#include "rtc.h"
#include "wkup.h"
#include "adc.h"
#include "dma.h"
#include "ds18b20.h"
extern u8 dmabuffer[8];
int main(void)
{
u16 j=0;
u16 i;
short temp;
Stm32_Clock_Init(6);//?μí3ê±?óéè??
delay_init(72); //?óê±3?ê??ˉ
uart1_init(72,9600); //′??ú13?ê??ˉ
uart3_init(36,115200); //′??ú33?ê??ˉ
RCC->APB2ENR|=1<<4; //ê1?üPORTCê±?ó
GPIOC->CRH&=0XFFF0FFFF;
GPIOC->CRH|=0X00030000;//PC12 í?íìê?3?
MYDMA_Config(DMA1_Channel2,(u32)&USART3->DR,(u32)dmabuffer,8,1);
MYDMA_Config(DMA1_Channel3,(u32)&USART3->DR,(u32)dmabuffer,8,0);
while(1)
{
temp=DS18B20_Get_Temp();
if(temp) printf("%d ",temp);
LED0=!LED0;//ìáê??μí3?y?ú??DD
}
}