selin1989的个人博客分享 http://blog.sciencenet.cn/u/selin1989

博文

关于STM32单片机学习的一些心得体会

已有 9109 次阅读 2015-5-26 21:36 |个人分类:科研心得|系统分类:科研笔记| 学习心得, 单片机, stm32

   已经五月底了,马上就要答辩了,快要离开校园了~走向新的工作岗位了。

   由于前段时间在公司里实习接触了STM32单片机,这次回校就准备好好学习学习~到现在为止,基本上是扎扎实实的学了半个月时间了,这半个月的时间里学习了基本IO口(GPIO),通用定时器,高级定时器,外部中断,Systick时钟,串口(232和485),CAN,I2C,DS18B20,程序加密等操作,除了CAN因为设备的限制,现在没法进行调试,其他的都已经调试成功了,在这段时间的学习和程序调试中学到了很多知识,也发现了一些STM32单片机的一些问题。

   一、232串口printf重映射的问题

   在刚刚开始用串口调试中,发现STM32单片的串口printf确实很方便,直接就可以把变量的值和字符直接送到上位机的串口调试助手中,但是在随着程序慢慢的变大,需要通过printf传输给上位机的数据越来越多。这时候问题就来了,容易导致系统的“串口死机”,注意:仅仅只是串口挂掉了,系统还是在正常运行。针对这个问题在网上找了一些资料,也没有完全解释清楚到底是什么问题,好像说是串口的缓存被挤爆了,然后进入了硬件中断从而导致串口失效,针对这种说法,我还没有进行验证,也不知道是否正确。只是我后来我将程序进行了修改,将所有的printf程序都注释掉,重新使用STM32的串口发送数据,这个问题就解决了。

   二、STM32的硬件I2C的问题

   在调试I2C之前,在网上也找了很多资料,很多人说STM32的硬件I2C有各种bug,难以调试等各种问题。就准备用软件进行模拟I2C的功能,但是调试中也遇到了各种时序问题,好长时间都没有调试成功。后来想了很久,既然STM32单片机现在卖的这么火,内部的硬件不可能出现这么大的问题,通过各种查资料,程序调试,经过了三天的紧张调试,终于将硬件I2C的功能调通了。其实说起来很简单,第一要主要I2C的引脚在复用中要使用开漏输出复用的模式,同时在硬件上,I2C端口需要4.7K上拉电阻。附上I2C硬件调试的原始程序,希望对后来者有帮助:

void I2C_Configuration(void)
{
   
   GPIO_InitTypeDef GPIO_InitStructure;//¶¨ÒåÒ»¸öGPIO¿Ú½á¹¹Ìå±äÁ¿
   I2C_InitTypeDef     I2C_InitStructure; //¶¨ÒåÒ»¸öI2C½Ó¿Ú½á¹¹Ìå
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE); //¹Ò½ÓI2C 2ʱÖÓ
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;       //PB10 SCL, PB11, SDA
   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;           //ÉèÖÃGPIOËÙ¶È
   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;             //¸´ÓÿªÂ©Êä³ö
   GPIO_Init(GPIOB,&GPIO_InitStructure);


   I2C_DeInit(I2C2);             //I2C2½Ó¿Úȱʡֵ£¬¸´Î»
   I2C_InitStructure.I2C_Mode=I2C_Mode_I2C; //I2C ģʽ
   I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;  //I2C¿ìËÙģʽ TLOW/THIGH=2
   I2C_InitStructure.I2C_OwnAddress1=0x30;   //×ÔÉíµØÖ· 0x30
   I2C_InitStructure.I2C_Ack=I2C_Ack_Enable; //ʹÄÜACKÓ¦´ð
   I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;  //Ó¦´ð7λµØÖ·
   I2C_InitStructure.I2C_ClockSpeed=200000;  // I2CʱÖÓËÙ¶È
   
   I2C_Init(I2C2,&I2C_InitStructure);        //³õʼ»¯ÅäÖÃ
   I2C_Cmd(I2C2,ENABLE);         //ʹÄÜI2C2    
}

/****************************************************************************
* Ãû  ³Æ  :void I2C_WriteByte(uint8_t DeviceAddress,uint16_t WriteAddr,uint8_t Buffer_Byte)
* ¹¦  ÄÜ  :дһ¸ö×Ö½ÚµÄÊý¾ÝдÈëI2C ÖÐ
* Èë¿Ú²ÎÊý:  DeviceAddress  ÒªÐ´ÈëµÄÉ豸µØÖ·
               Buffer_Byte  ÒªÐ´ÈëµÄ×Ö½Ú
                     WriteAddr ҪдÈëÉ豸µÄ¼Ä´æÆ÷µØÖ·
* ³ö¿Ú²ÎÊý:ÎÞ
* ˵  Ã÷  :
* µ÷Ó÷½·¨:ÎÞ
****************************************************************************/

void I2C_WriteByte(uint8_t DeviceAddress,uint16_t WriteAddr,uint8_t Buffer_Byte)
{
   uint8_t addr1,addr2;
   addr1=DeviceAddress+((WriteAddr/256)<<1);  
   addr2=WriteAddr%256;
   
   I2C_GenerateSTART(I2C2,ENABLE);   //·¢ËÍÆðʼÐźÅ
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT));  //·¢ËÍÍê±Ï EV5

   I2C_Send7bitAddress(I2C2,addr1,I2C_Direction_Transmitter); //ÏòÉ豸·¢ËÍÉ豸µØÖ·
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));   //·¢ËÍÍê³É EV6
   I2C_AcknowledgeConfig(I2C2,DISABLE);        //ʧÄÜI2CµÄÓ¦´ð¹¦ÄÜ
   I2C_SendData(I2C2,addr2);    //·¢ËͼĴæÆ÷µØÖ·
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //·¢ËÍÍê³ÉEV8
   I2C_AcknowledgeConfig(I2C2,DISABLE);       //ʧÄÜI2CµÄÓ¦´ð¹¦ÄÜ      

   I2C_SendData(I2C2,Buffer_Byte);
   while(!(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)));  //·¢ËÍÍê³ÉEV8
   I2C_GenerateSTOP(I2C2,ENABLE);        //·¢ËÍÍ£Ö¹ÐźÅ
   Delay_10ms();
}

/****************************************************************************
* Ãû  ³Æ  :void I2C_ReadByte(uint8_t DeviceAddress,uint16_t ReadAddr,uint8_t *pBuffer)
* ¹¦  ÄÜ  :½«I2C ÖеÄÒ»¸ö×Ö½ÚÊý¾Ý¶Á³ö·ÅÈëpBuffer »º´æÖÐ
* Èë¿Ú²ÎÊý:  DeviceAddress  Òª¶Á³öµÄÉ豸µØÖ·
               pBuffer  »º³åÇøµØÖ·Ö¸Õë
                     WriteAddr Òª¶Á³öÉ豸µÄ¼Ä´æÆ÷µØÖ
* ³ö¿Ú²ÎÊý:¶ÁÈ¡ÊÇ·ñ³É¹¦
* ˵  Ã÷  :
* µ÷Ó÷½·¨:ÎÞ
****************************************************************************/
void I2C_ReadByte(uint8_t DeviceAddress,uint16_t ReadAddr,uint8_t *pBuffer)
{
   uint8_t addr1,addr2;
   addr1=DeviceAddress+((ReadAddr/256)<<1);
   addr2=ReadAddr%256;

   I2C_GenerateSTART(I2C2,ENABLE);       //·¢ËÍÆðʼÐźÅ
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT));  //EV5 ·¢ËÍÍê³É
   I2C_Send7bitAddress(I2C2,addr1,I2C_Direction_Transmitter);  //ÏòÉ豸·¢ËͶÁÈ¡É豸µØÖ·
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//·¢ËÍÍê³É EV6
   I2C_Cmd(I2C2,ENABLE);      //ʹÄÜI2C
   I2C_AcknowledgeConfig(I2C2,DISABLE);     //ʹÄÜI2CµÄÓ¦´ð¹¦ÄÜ
   I2C_SendData(I2C2,addr2);  //·¢ËͶÁ¼Ä´æÆ÷µØÖ·

   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //·¢ËÍÍê³É EV8
   I2C_AcknowledgeConfig(I2C2,DISABLE);      //ʧÄÜI2CµÄÓ¦´ð¹¦ÄÜ
   I2C_GenerateSTART(I2C2,ENABLE);  //ÖØз¢¿ªÊ¼ÃüÁî
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)); //·¢ËÍÍê³É EV5
   I2C_Send7bitAddress(I2C2,addr1+1,I2C_Direction_Receiver); //·¢ËͶÁÈ¡É豸µØÖ·
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//·¢ËÍÍê³ÉEV6
   while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED)); //½ÓÊÕÊý¾ÝÍê±Ï EV7
   I2C_AcknowledgeConfig(I2C2,DISABLE);  //ʧÄÜI2CµÄÓ¦´ð¹¦ÄÜ
   *pBuffer=I2C_ReceiveData(I2C2);  //½ÓÊÕI2C
   I2C_GenerateSTOP(I2C2,ENABLE);  //·¢ËÍÍ£Ö¹ÐźÅ
}

另外软件模拟I2C的程序就不上传了,比较长,网上这方面的内容还是比较多的,大家多找找~


今天就先讲这么多,晚上还得技术调试SPI接口,希望不会出现问题,可以顺利的搞完~~~~~~~~~~~





https://wap.sciencenet.cn/blog-865050-893323.html

上一篇:小信号放大与信号检波
收藏 IP: 218.2.227.*| 热度|

1 吕喆

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-19 08:05

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部