这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 只能到此为止了-dqluyanshu 之ARMDIY进程帖

共32条 3/4 1 2 3 4 跳转至
菜鸟
2012-05-30 14:02:29     打赏
21楼

         3.1 DS18B20检测温度,LCD显示
 这个东东也是调了好多天,最后不知为啥早上就可以工作了,真奇妙,先上图

一开始想自己写源程序的,可是最后DS18B20总是不响应,最后只得又换了源程序,只是修改了下温度的算法,在此把源程序贴上,供大家修改指正
 void  main(void)
{
   float num;
   char b[250];
   
   RCC->CFGR|=0x00180002;
   RCC->CR|=0x01000001;  
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
         | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG
         | RCC_APB2Periph_AFIO , ENABLE);
  /*------------------- Resources Initialization -----------------------------*/
      
    LCD_Clear(Magenta);
    LCD_SetTextColor(Blue);
    LCD_SetBackColor(Magenta);
    LCD_DisplayString(50, 50, "the temperature is");
 
    STM32_LCD_Demo();
  
    while(1)
    {  
    num=readtemperature();
   
    sprintf(b," %f",num); 
    LCD_DisplayString(50, 80, (uint8_t*)b);
    delay_1ms(10);
    }

}



void STM32_LCD_Demo(void)
{
 

  /* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
         | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG
         | RCC_APB2Periph_AFIO , ENABLE);
 
/*------------------- Resources Initialization -----------------------------*/
  /* GPIO Configuration */
   GPIO_Config();

   /* Initialize the LCD */
   STM3210E_LCD_Init(); 
}


最后是DS18B20的程序,由于使用时钟滴答器即时较准,一开始以为蛮难的,其实很简单的,就跟设置定时器一样简单。
#include "stm32f10x_gpio.h"

#define DS_PORT GPIOA    //选择外设GPIOA
#define DS_DQIO GPIO_Pin_1    //选择管脚Pa1
#define ResetDQ() GPIO_ResetBits(DS_PORT,DS_DQIO)  //拉低DQ
#define SetDQ() GPIO_SetBits(DS_PORT,DS_DQIO)   //拉高DQ
#define GetDQ() GPIO_ReadInputDataBit(DS_PORT,DS_DQIO) //读取DQ的电平
#define skipRom 0xcc
#define convert 0x44
#define readTemp 0xbe

void delay_1ms(uint16_t cnt)
{
 uint16_t i;
 while(cnt--)
 for(i=0;i<8300;i++);
}

void delay_1us(uint32_t value)
{
 SysTick->LOAD=value*9; //时间加载
 SysTick->CTRL|=0x01;   //开始倒数
 while(!(SysTick->CTRL&(1<<16))); //等待时间到达
 SysTick->CTRL=0x00000000;  //关闭计数器
 SysTick->VAL=0x00000000;   //清空计数器 
}

void Init_ds18b20(void)    //初始化DS18B20
{
        GPIOA->CRL=0x44444474;
 SetDQ();
 delay_1us(30);  //保持高电平一段时间时间
 ResetDQ();  //总线将其拉低电平
 delay_1us(600);    //延时400us-960us,这里延时600us
 SetDQ();             //总线释放低电平
 delay_1us(30);   //延时15us-60us,这里延时30us
       
        GPIOA->CRL&=0xFFFFFF4F;  
 while(GetDQ());   //若为高电平则出错,等待一直循环
 delay_1us(500); //将剩余时间消耗完
 SetDQ();  //总线将电平拉高
}


void DS18B20WriteByte(uint8_t Dat)
{
 uint8_t i;
        GPIOA->CRL=0x44444474;
 for(i=8;i>0;i--)
 {
         
  ResetDQ();    //在15us内送数到数据线,在15-60us内采样
  delay_1us(5);

  if(Dat&0x01) //读数据的最低位
  SetDQ();
  else
  ResetDQ();

  delay_1us(65); //将剩余时间消耗完
  SetDQ();
  delay_1us(2); //写两个位之间间隔大于1us
  Dat>>=1;   //右移一位,
 }
}

uint8_t DS18B20ReadByte(void)
{
 uint8_t i,Dat;
 //SetDQ();
 //delay_1us(5);
 for(i=0;i<8;i++)
 {
                GPIOA->CRL=0x44444474;
                SetDQ();  //拉高总线
                delay_1us(5);
  Dat>>=1;
  ResetDQ(); //从读时序开始到采样信号线必须在15us内,且采样尽量安排在15us最后
  delay_1us(5);
  SetDQ(); //释放总线,然后才能进行采样,否则无意义。只有低电平
  delay_1us(5);
               
                GPIOA->CRL&=0xFFFFFF4F; 
  if(GetDQ())
   Dat|=0x80;
  else
   Dat&=0x7f;delay_1us(5);
  delay_1us(65);  //消耗剩余时间
               
  
 }
 return Dat;
}

float readtemperature(void)
{
 uint8_t a,b;
        float cach;
 Init_ds18b20(); //初始化
 DS18B20WriteByte(skipRom);
 DS18B20WriteByte(convert); //开始转换温度
 delay_1ms(550);  //延时,等待温度转换完成

 Init_ds18b20();
 DS18B20WriteByte(skipRom);
 DS18B20WriteByte(readTemp); //读取暂存器

 a=DS18B20ReadByte();    //读取低8位
 b=DS18B20ReadByte(); //读取高8位
       
        if(b&0xF8)
        {
          a=~a;
          cach=a&0x0F;
          cach=(cach+1)*0.0625;
          b=~b;
          b<<=4;
          b+=(a&=0xf0)>>4;
          cach+=b;
          return cach;                  
        }
        else
        {
           cach=a&0x0F;
           cach*=0.0625;
           b<<=4;
           b+=(a&=0xf0)>>4;
           cach+=b;
           return cach;           
        }

}


菜鸟
2012-05-30 14:14:18     打赏
22楼

                    3.2 DA产生正弦波源程序
这个是做实验中最快实现的一个 应该还算简单吧,也许是我比较幸运吧


使用DAC1

产生的正弦波

源程序很简单的,大家可以试验下
#include<main.h>

void  main(void)
{
     uint16_t i;
     RCC->CFGR|=0x00180002;
     RCC->CR|=0x01000001;
 
    /* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);                
     while(1)
     {
       for(i=0;i<360;i++)
       {
        
       DAC->DHR12R1=dot[i];     
           
       DAC->CR=0x00000001;
      
       delay_1us(1);       
       }
     }
 
}

就设置了两个寄存器,哦,对了 还要找那个正弦波产生软件
提供个地址
http://www.ceet.hbnu.edu.cn/bbs/viewthread.php?tid=4843

我产生的正弦波点数

uint32_t dot[360]={0x800,0x823,0x847,0x86b,0x88e,0x8b2,0x8d5,0x8f9,0x91c,0x940,0x963
       ,0x986,0x9a9,0x9cc,0x9ef,0xa11,0xa34,0xa56,0xa78,0xa9a,0xabc,0xadd,0xafe,
        0xb1f,0xb40,0xb61,0xb81,0xba1,0xbc1,0xbe0,0xbff,0xc1e,0xc3c,0xc5a,0xc78,
        0xc96,0xcb3,0xccf,0xcec,0xd08,0xd23,0xd3f,0xd59,0xd74,0xd8e,0xda7,0xdc0,
        0xdd9,0xdf1,0xe09,0xe20,0xe37,0xe4d,0xe63,0xe78,0xe8d,0xea1,0xeb5,0xec8,
        0xeda,0xeed,0xefe,0xf0f,0xf20,0xf30,0xf3f,0xf4e,0xf5c,0xf6a,0xf77,0xf84,
        0xf90,0xf9b,0xfa6,0xfb0,0xfb9,0xfc2,0xfcb,0xfd2,0xfda,0xfe0,0xfe6,0xfeb,
        0xff0,0xff4,0xff8,0xffa,0xffd,0xffe,0xfff,0xfff,0xfff,0xffe,0xffd,0xffb,
        0xff8,0xff4,0xff0,0xfec,0xfe7,0xfe1,0xfda,0xfd3,0xfcb,0xfc3,0xfba,0xfb1,
        0xfa7,0xf9c,0xf91,0xf85,0xf78,0xf6b,0xf5d,0xf4f,0xf40,0xf31,0xf21,0xf11,
        0xf00,0xeee,0xedc,0xec9,0xeb6,0xea3,0xe8e,0xe7a,0xe64,0xe4f,0xe39,0xe22,
        0xe0b,0xdf3,0xddb,0xdc2,0xda9,0xd90,0xd76,0xd5c,0xd41,0xd26,0xd0a,0xcee,
        0xcd2,0xcb5,0xc98,0xc7b,0xc5d,0xc3f,0xc21,0xc02,0xbe3,0xbc3,0xba4,0xb84,
        0xb64,0xb43,0xb22,0xb01,0xae0,0xabf,0xa9d,0xa7b,0xa59,0xa37,0xa14,0x9f2,
        0x9cf,0x9ac,0x989,0x966,0x943,0x920,0x8fc,0x8d9,0x8b5,0x892,0x86e,0x84a,
        0x826,0x803,0x7df,0x7bb,0x798,0x774,0x750,0x72d,0x709,0x6e6,0x6c3,0x69f,
        0x67c,0x659,0x636,0x613,0x5f1,0x5ce,0x5ac,0x58a,0x568,0x546,0x525,0x504,
        0x4e3,0x4c2,0x4a1,0x481,0x461,0x441,0x422,0x403,0x3e4,0x3c5,0x3a7,0x389,
        0x36c,0x34f,0x332,0x316,0x2fa,0x2de,0x2c3,0x2a8,0x28e,0x274,0x25a,0x241,
        0x228,0x210,0x1f9,0x1e1,0x1cb,0x1b4,0x19e,0x189,0x174,0x160,0x14c,0x139,
        0x126,0x114,0x102,0xf1,0xe1,0xd1,0xc1,0xb2,0xa4,0x96,0x89,0x7d,0x71,0x65,
        0x5a,0x50,0x46,0x3d,0x35,0x2d,0x26,0x1f,0x19,0x14,0xf,0xb,0x8,0x5,0x3,
        0x1,0x0,0x0,0x0,0x1,0x2,0x4,0x7,0xa,0xe,0x13,0x18,0x1e,0x24,0x2b,0x33,
        0x3b,0x44,0x4d,0x57,0x62,0x6d,0x79,0x86,0x93,0xa0,0xae,0xbd,0xcc,0xdc,
        0xed,0xfe,0x10f,0x121,0x134,0x147,0x15b,0x16f,0x183,0x199,0x1ae,0x1c4,
        0x1db,0x1f2,0x20a,0x222,0x23a,0x253,0x26d,0x287,0x2a1,0x2bc,0x2d7,0x2f2,
        0x30e,0x32a,0x347,0x364,0x381,0x39f,0x3bd,0x3dc,0x3fa,0x419,0x439,0x458,
        0x478,0x498,0x4b9,0x4da,0x4fb,0x51c,0x53d,0x55f,0x581,0x5a3,0x5c5,0x5e7,
        0x60a,0x62d,0x650,0x673,0x696,0x6b9,0x6dc,0x700,0x723,0x747,0x76a,0x78e,
        0x7b2,0x7d5};
void delay_1us(uint32_t value)
{
 SysTick->LOAD=value*9; //时间加载
 SysTick->CTRL|=0x01;   //开始倒数
 while(!(SysTick->CTRL&(1<<16))); //等待时间到达
 SysTick->CTRL=0x00000000;  //关闭计数器
 SysTick->VAL=0x00000000;   //清空计数器 
}

嘻嘻 又用了下systick,发现还蛮好用的

 


高工
2012-06-02 05:57:37     打赏
23楼
不错!

菜鸟
2012-06-02 23:30:06     打赏
24楼
取的点不够多,看那波形还有【毛刺】

菜鸟
2012-06-07 16:53:22     打赏
25楼

       3.3  I2C模块数据存储,STM32读取数据显示
      目前只能实现单个数据的传送,关于页的读写,还没有实现,呵呵,时间不多了,还是抓紧赚分吧。等忙完了 再好好琢磨琢磨。
 I2C模块的读写差不多又查了一个星期的资料,知道昨天才清楚问题在哪,我一直想用STM32提供库文件,因为觉得以后用起来会更方便,可是这次的I2C读写问题就出来了,我是用STM32中I2C模块来通信的,而不是用I/O软件模拟出来的,调了三四天,
就卡下面这个程序上,
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));硬件就是无应答。

昨天才知道原来STM32有个硬件BUG,就是I2C模块和FSMC模块是冲突的,我是用FSMC模块来驱动LCD,这样的话自然使用LCD的情况下,I2C模块可能就无法启动,于是先传递了数据,再初始化使能LCD,没想到 还真就行了。

《如果打开了FSMC时钟,即使不用FSMC_NADV引脚,但是这个引脚还是默认成高电平;从而于I2C1_SDA冲突。》


总结一下,有两点需要注意,一是I2C模块工作前,必须关掉FSMC时钟,二是必须在 停止条件后才能读数据即I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件后  date = I2C_ReceiveData(I2C1);  //读数据,这样数据才会正确传递。不说了 上源程序

void main()
{
    char byte[100];
    uint8_t cach;  

    I2C1_Init();  //初始化I2C1模块
    I2C_WRITE(2,0x33); //写数据到DR寄存器
    Delay(1000);
    cach=I2C_READ(2); //读数据到cach变量中
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE);
   
    sprintf(byte,"%x",cach);
   
  
    STM32_LCD_Demo();//必须放在I2C模块之后使能
    LCD_DisplayString(50, 50, "write string is 0x33");
    LCD_DisplayString(50,70, "read string is");  

    LCD_DisplayString(50,90,(uint8_t*)byte);  
    while(1)
    {
    }
}

重点在这里 I2C1_Init()
void I2C1_Init(void) 
{
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);

  GPIO_Configuration();  

  I2C_Configuration();

AT24C02的读写程序,这才是关键,不过只适合demo。因为只可以传递单个数据,分页读写还没研究
void I2C_WRITE(uint8_t WriteAddr,uint8_t date)//写数据到内部地址writeAddr
{
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  //等应答
   
    I2C_Send7bitAddress(I2C1, 0xa0, I2C_Direction_Transmitter);//写器件地址
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  
    I2C_SendData(I2C1, (uint8_t)(WriteAddr>>8));     // MSB
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2C1, (uint8_t)(WriteAddr));     // lSB
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2C1,date);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTOP(I2C1, ENABLE);    
    Delay(25000);
}

uint8_t I2C_READ(uint8_t ReadAddr) //随机读
{

    uint8_t date;

    I2C_GenerateSTART(I2C1, ENABLE);   
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 
    I2C_AcknowledgeConfig(I2C1, DISABLE);

    I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);   
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
   
    I2C_SendData(I2C1, (uint8_t)(ReadAddr>>8));     // MSB
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2C1, (uint8_t)(ReadAddr));     // lSB
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

   
    I2C_GenerateSTART(I2C1, ENABLE);   
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //等应答
   
    I2C_Send7bitAddress(I2C1, 0xa1, I2C_Direction_Receiver);  
    while(!(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)));           

    I2C_GenerateSTOP(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));   
   
 
    date = I2C_ReceiveData(I2C1);  //开启主机I2C的应答功能

    return date;           
}
嘻嘻 ,这两个函数对于STM32的开发板四绝对好用的哦。
调的好烦,不过出来结果还是蛮高兴的。


菜鸟
2012-06-11 17:31:47     打赏
26楼
                     3.4      定时器中断终于可以了

哎 好辛苦啊,调程序调的晕头转向,不过终于被俺给搞定了

本程序实现用定时器2溢出中断,使LED灯闪烁

上传整个工程文件 到请需要者自行下载。
程序下载地址:
http://share.eepw.com.cn/share/download/id/75869

以下贴出我遇到的几个问题,及解决方法,希望像我一样的初学者可以少走弯路
在应用中断之前,有些前提条件是必须的,相信大家很容易找到,比如使能中断,添加NVIC 设置,以及添加中断响应函数。
首先系统初始化,IO口、中断初始化
  SystemInit();
  GPIO_Configuration();
  Init_NVIC();
  Timer_Configuration();
  while(1);
然后必须添加启动文件才可以确定中断向量表所在位置,才可以使用中断,所在目录可参考
启动文件时根据编译下载软件及IC类型决定的,因为我们用的IC是大容量的所以选用startup_stm32f10x_hd.s,添加到工程即可。因为我使用的IAR软件编译下载,所以去IAR安装目录里找

PS.中断处理函数一般在stm32f10x_it.c中定义找到TIM2_IRQHandler(void)函数,添加IO口置位函数即可


还有我参考的一些挺有用的文献
http://hi.baidu.com/seipher/item/707d2c290837eff851fd8716
http://wenku.baidu.com/view/674571cea1c7aa00b52acb3e.html?from=rec&pos=1&weight=302&lastweight=261&count=5
http://wenku.baidu.com/view/f2c1dc04cc1755270722083a.html?from=rec&pos=1&weight=23&lastweight=19&count=5

高工
2012-06-14 22:36:55     打赏
27楼
加油啊~!

菜鸟
2012-06-15 18:24:32     打赏
28楼

        看了几天的USB资料,想这星期把它调调试试的,可是深圳这破天气,时不时的来点雨,淋了一场雨,发了高烧,几天都昏昏欲睡,这次的活动也只能到此为止了,虽然调出来的不多,但总有了些经验,有了些收获,有时间会把其他部分一一调出 一定。
      首先,夸奖下自己,可以认真的从头调到尾,继续努力,加油
其次要感谢举办这次活动的人,画这个PCB板的人,给了自己一次奋斗的机会,一次热情的尝试,这里说声谢谢


菜鸟
2012-12-14 13:36:20     打赏
29楼
今天看帖子发现楼主的工具貌似是IAR原厂的啊

专家
2012-12-14 22:29:17     打赏
30楼
尽量就好!不可强求

共32条 3/4 1 2 3 4 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]