基于STM32+iCE40的电赛训练平台制作的频率计
基于STM32+iCE40的电赛训练平台,项目5 - 频率计,利用板上的高速比较器和STM32代码实现频率计的功能,并在OLED屏幕上显示出被测信号的频率
标签
嵌入式系统
亚历鸽斯
更新2023-03-28
西安电子科技大学
443

内容介绍

项目描述:

该项目是一个基于STM32+iCE40的电赛训练平台制作的频率计,利用板载的STM32G031G8U6作为主控,通过板载的高速比较器作为波形输入的整形,通过STM32捕获信号,进行波形测量并在OLED上进行显示。

任务要求:

利用STM32+iCE40的电赛训练平台制作的一款频率计,实现对输入波的频率的测量。

设计思路:

该频率计通过STM32的TIM3 CH1输出一段pwm波给高速比较器,与输入的波形进行比较,整形,输出一段方波给PA1引脚。波形的捕获采用上升沿中断触发,以1s作为周期进行计数。计数后将结果在OLED屏幕上呈现。OLED使用软件模拟SPI进行驱动。

设计框图:

 

FvkG6atWi55EpRU3KCcts10wSEmv

程序流程图:

 

FsbcAZUBvwRic0wsjZCl8GBRefu7

MCU配置展示:

FkHMr9XzQp8qlqsHPoMr7HnLi0Bs

由于OLED的驱动采用软件模拟SPI,故在工程文件的配置中只需开四个GPIO口即可

PA0 -- SCL

PA4 -- SDA

PA5 -- RES

PA8 -- DC

 

主函数代码:

int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */
	OLED_Init();
	OLED_ColorTurn(1);
	OLED_DisplayTurn(0);
	OLED_ShowString(0,0,"Freq Counter/Hz",16);
	OLED_ShowString(0,16,"Made by AlexZ",16);
	OLED_ShowString(0,32,"freq:",16);
	OLED_Refresh();
	
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, 50);
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
pwm_value = 0; // pwm_value置0,这个是必须要做的,数据要刷新
		HAL_Delay(1000); // 延时1s
		OLED_ShowNum(75,32,pwm_value,6,16);
		OLED_Refresh();
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

简单的进行一个OLED屏幕的显示

在while循环中通过hal_delay进行一个1s的延时,在延时过程中每个输入PA1脚的上升沿都会触发中断服务,以下为中断服务函数

void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
	pwm_value++;
}

延时结束后,pwm_value值即为输入波的频率,将pwm_value的值显示在OLED上。

软件模拟的SPI的驱动会相对容易移植,只需要在oled.h文件中配置好对应引脚即可,如下:

//PA0
#define SCL_GPIO_Port GPIOA
#define SCL_Pin GPIO_PIN_0
#define OLED_SCL_Clr() HAL_GPIO_WritePin(SCL_GPIO_Port,SCL_Pin,GPIO_PIN_RESET)
#define OLED_SCL_Set() HAL_GPIO_WritePin(SCL_GPIO_Port,SCL_Pin,GPIO_PIN_SET)

//PA4
#define SDA_GPIO_Port GPIOA
#define SDA_Pin GPIO_PIN_4
#define OLED_SDA_Clr() HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_RESET)
#define OLED_SDA_Set() HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_SET)

//PA5
#define RES_GPIO_Port GPIOA
#define RES_Pin GPIO_PIN_5
#define OLED_RES_Clr() HAL_GPIO_WritePin(RES_GPIO_Port,RES_Pin,GPIO_PIN_RESET)
#define OLED_RES_Set() HAL_GPIO_WritePin(RES_GPIO_Port,RES_Pin,GPIO_PIN_SET)

//PA8
#define DC_GPIO_Port GPIOA
#define DC_Pin GPIO_PIN_8
#define OLED_DC_Clr() HAL_GPIO_WritePin(DC_GPIO_Port,DC_Pin,GPIO_PIN_RESET)
#define OLED_DC_Set() HAL_GPIO_WritePin(DC_GPIO_Port,DC_Pin,GPIO_PIN_SET)

 

PS.本项目未使用FPGA,故无FPGA资源占用报告

 

实物功能展示:

 

FsEahW6kUb2Kb2dCe8T5uuiyer4c

可以看到在频率达到60.0000Hz左右,频率计依然能够相对比较准确地显示方波的频率。

理论上最大可以检测的频率应该在639999左右。

 

后记:

遇到的主要难题:

六脚SPI的OLED驱动的移植

0.96寸的OLED显示屏还是很常见的,国内开源平台上有很多可供下载的OLED驱动,适配了多种通信方式,如SPI和IIC。常见的SPI驱动又有软件SPI和硬件SPI。相较之下软件SPI虽然速度比硬件SPI更慢,但是移植起来更加快捷,使用也更加稳定,只要在头文件修改对应的GPIO_Port和GPIO_PIN即可,具体直接参考原理图即可。至于说问题(也不能说是问题),到底就是在OLED屏init和showstring后忘了加refresh,导致OLED屏幕移植不能正常显示,就这样干耗了半天,误以为是软硬件或者各种杂七杂八的问题,我是憨批。总之记得移植驱动前仔细看例程和注释。

软件的debug

问题就是不能debug。串口烧录程序,好处就是方便,不需要使用STLINK,直接使用STM32CubeProgrammer进行串口烧录即可。坏处就是不能在上位机上实时跑程序进行监控以及debug。但是考虑到此次制作频率计的任务相对简单,所以不能debug没有造成太大的问题。

没有外部晶振

本次使用的小脚丫基于STM32G031 + iCE40UP5K的MCU+FPGA核心板上的12MHz晶振接在了ICE40UP5k上,所以STM32没有提供外部晶振,只能使用内部时钟。使用内部时钟的问题是随着板子的使用,可能造成发热影响内部时钟的准确性,对于检测信号频率的准确性大概是有影响的。

后续优化:

考虑到在下此次任务完成时间紧迫,所以只是最底线的实现了信号频率捕获以及显示的功能。还有很多功能没有用上,比如旋转编码器、按键还有板子上那块牛逼哄哄的ICE40等等。

对于具体的优化,理论上,首先可以实现添加按键及旋转编码器的功能,譬如通过按键实现屏幕颜色的正反转,通过编码器调整PWM输出的频率等等。至于ICE40,可以实现的功能就更多了,比如通过高速DAC实现输出一个初始波形,在没有外部输入的时候可以有一个初始波形,进行校验、检视等等。同时在程序的逻辑上,还有很多可以进行优化的。比如程序采用的阻塞式延时,这在大项目的开发中是比较忌讳的。考虑到是小项目所以图方便直接使用网上找的方案直接hal_delay,也不会造成太大的影响,后续优化可以使用定时器中断。其次示数的刷新率为1Hz,还是挺慢的,可以通过减短采样时间来提高刷新率。再有就是freq的示数存在浮动,可以考虑再额外输出一个平均值。

未来的计划及建议

该项目已经成功实现了简易频率计的功能,并达到了预期指标。但是通过硬件的优化,还有许多提升和拓展的空间。

首当其冲就是把SWDIO和SWCLK引出来,能够实现debug,能够很大程度提高开发的便捷性。

还有就是可以再加个按键作为stm32的reset。不然每次重置都需要下电还是不太优雅。可以考虑把reset、boot0、boot1通过开关进行控制。(就像我手头这块f401一样:

 

FqJpqMx4f-NGyABo_ma8pDm8Sm5e

 

工程文件如下

链接:https://pan.baidu.com/s/1_sdcJ-g1IazkYd_gFTd9hg?pwd=alex 
提取码:alex

团队介绍

就我一个

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号