分享

调试成功用串口DMA驱动单总线DS18b20

 guitarhua 2014-12-04
在网上参考了两个人的思想原理后动工,3天内搞定!其实也就是ds2408的工作原理,参考文献列出如下:
在STM32上通过UART+DMA实现One-Wire总线
http://www./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

  
}
}


















    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多