STM32开发日志

3 篇文章 0 订阅
2 篇文章 0 订阅

、STM32单片机外接16Mhz晶振时,需要更改单片机头文件里关于时钟的宏定义以及 system_stm32f0xx.c中的倍频数,因为默认是8Mhz。如会导致串口打印乱码等。
在这里插入图片描述

16M * 3 = 48M在这里插入图片描述

问题:焊接下图这种封装的芯片时,UFQFPN32封装,底部为GND时,如果与焊盘虚焊,那么可能导致能读到芯片但是下载不了程序。
在这里插入图片描述

问题:
烧录程序后就不能再次烧录程序了,且读不到芯片。
解决:可能是上一次烧录的程序导致下载引脚被禁用,此时将BOOT0引脚拉高就可读取到芯片,下载一个没有禁用引脚的程序即可。也可使用Jlink软件进行Flash的整块擦除。


问题:串口发送连续数据包不完整。当上位机下发给单片机查询数据包时,单片机应该进行数据的回复,但实际发现只回复了包内的两个数据回来,因为回来的数据包是连续发送的。单步调试的时候回来的数据包完整,全速运行时回来的数据包只有两个数据。
解决:在每发一个字节的数据后加上延时,即可解决。

、移植同系列其他芯片工程时,需要更改头文件的宏定义。如使用STM32F051的工程模板改为STM32F031,那么需要更改stm32f0xx.h中的宏定义:
在这里插入图片描述
、STM32串口发送连续的数据出去的时候,使用while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);这条语句将会更好,这里面的USART_FLAG_TC标志位是发送完成标志位。

、晶振知识与嘀嗒定时器:1M的晶振就1s震动1000000次,那么振动1次就是0.000001s,也就是1us。就SYStick定时器为例,当其时钟为系统时钟(48M)的8分频后得到的时钟为6M,那么该时钟1s震动6000000次,1us震动6次;同理,定时器的分频系数也一样。
在这里插入图片描述
、LWIP连接过程中更改IP地址
1、关闭端口、强制删除TCP_server主动断开时的Time_Wait、释放pcb控制块的内存和对应的数组
在这里插入图片描述

2、初始化IP,网关,子网掩码,禁用网卡,重设IP,网关,子网掩码,启用网卡。
在这里插入图片描述

3、创建服务器即可或直接可以ping通

、STM32程序运行一段时间后程序卡在“0x0800XXXX BEAB BKPT 0xAB”处,可能是使用了printf函数导致的,解决方法如下:

#include "stdio.h"

//----------------------------//
#pragma import(__use_no_semihosting)                     
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 __stdout;       
void _sys_exit(int x) 
{ 
	x = x; 
} 

//重定向printf函数
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);
	USART1->DR = (u8) ch;      
	return ch;
}

//---------------------------------//

、STM32程序使用内部参考电压作为基准,其他通道采集电压,开启ADC采集完成后关闭ADC,导致功耗上升30ua左右,解决方法:
1、关闭ADC电压调节器
2、关闭ADC参考电压通道
3、关闭ADC时钟
其他通道电压计算公式:
Vchx = VrefInt * (ADchx/ADrefInt);
Vchx : 通道x的电压
VrefInt :STM32内部参考电压,通过数据手册查看约为1.2v左右
ADchx:通道x实际采集到的电压
ADrefInt:内部通道采集到的电压
代码如下:

// PB1----ADC_IN8 
void ADInit(void)
{
     RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
     /* (1) Select HSI16 by writing 00 in CKMODE (reset value) */ 
     /* (2) Select the auto off mode */
     /* (3) Select CHSEL17 for VRefInt */
     /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */
     /* (5) Wake-up the VREFINT (only for VLCD, Temp sensor and VRefInt) */
     ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */    
     ADC1->CFGR1 |= ADC_CFGR1_AUTOFF; /* (2) */
     ADC1->CHSELR = ADC_CHSELR_CHSEL17;//ADC_CHSELR_CHSEL3; /* (3) 
     ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */
     ADC->CCR |= ADC_CCR_VREFEN; /* (5) */
     
     
     /* (1) Ensure that ADEN = 0 */
     /* (2) Clear ADEN */ 
     /* (3) Set ADCAL=1 */
     /* (4) Wait until EOCAL=1 */
     /* (5) Clear EOCAL */
     if ((ADC1->CR & ADC_CR_ADEN) != 0) /* (1) */
     {
          ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);  /* (2) */  
     }
     ADC1->CR |= ADC_CR_ADCAL; /* (3) */
     while ((ADC1->ISR & ADC_ISR_EOCAL) == 0) /* (4) */
     {
    /* For robust implementation, add here time-out management */
     }  
     ADC1->ISR |= ADC_ISR_EOCAL; /* (5) */
     
     /* (1) Enable the ADC */
     /* (2) Wait until ADC ready if AUTOFF is not set */
     ADC1->CR |= ADC_CR_ADEN; /* (1) */
     if ((ADC1->CFGR1 &  ADC_CFGR1_AUTOFF) == 0)
     {
          while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (2) */
          {
               /* For robust implementation, add here time-out management */
          }
     }
     
}
// 4.
u16 GetBatADCValue(void)
{
     u16 dat1,dat;
     float vol;
     BatteryOn;
     ADInit();
     ADC1->CR |= ADC_CR_ADSTART;
     while ((ADC1->ISR & ADC_ISR_EOC) == 0); /* wait end of conversion */
     dat1 = ADC1->DR;
     
     ADC1->CHSELR = ADC_CHSELR_CHSEL9;
     ADC1->CR |= ADC_CR_ADSTART;
     while ((ADC1->ISR & ADC_ISR_EOC) == 0); /* wait end of conversion */
     dat = ADC1->DR;
     BatteryOff;
     DisableADC();
     
     vol = 1.2 * ((float)dat/(float)dat1) * 2 + 0.08;

     Card.Bat = ((u8)(vol*10)) & 0x3F;
     RangeData.Bat = Card.Bat;
     
     if(vol < 3.4)
          Card.Flag |= 0x04;
     else
          Card.Flag &= ~0x04;
     return dat;
}

十一、STM32G030F6 SPI1移植问题

u8 SendByteLora(u8 value)
{
	while(LL_SPI_IsActiveFlag_TXE(SPI1) == 0);
	LL_SPI_TransmitData8(SPI1,value);
	while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0);
	return LL_SPI_ReceiveData8(SPI1);
//	while((SPI1->SR & (1<<1)) == 0);
//	SPI1->DR = value;
//	while((SPI1->SR & (1<<0)) == 0);
//	return SPI1->DR;
}

注释的部分是L051可用的程序,移植到G030就用不了,后使用CUBEMX生成的LL库就可以用,有空查下原因

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值