单片机项目中使用新IC芯片的调试方法

前言:我们在单片机的项目开发过程中经常会遇到使用新IC芯片的情况,某宝卖家有个时候也提供不了对应开发程序,到网上找资料也找不到;很多初学者面对这样的问题往往束手无策,这里我给大家介绍我经常用的其中一种新IC调试的方法。
因为这个芯片比较简单我这里采用下面步骤进行:
第一步:先用arduino+面包板快速搭建电路验证芯片功能
第二步:使用STM32CubeIDE快速搭建工程验证在STM32上工作是否正常
Tips:由于我手头没有万用表,这里我使用arduino的模拟电压采集功能通过串口打印出来作为电位计的电压监控用。
首先,我们先快速浏览芯片数据手册,获取重要信息
IC型号:TPL0501
电压范围:2.7~5.5V
温度范围:-40~125℃
通信方式:SPI
阻值:100KΩ
阻值偏差:±20%
该芯片是某州仪器的一款单通道数字电位计,通信方式是SPI总线,单方向的,即只能控制芯片,不能读取输入数据,下面是数据手册的具体介绍。
环境参数:主要包括温度使用范围、电压使用范围、误差、温度漂移以及实物引脚对应关系都在这里
功能框图:主要介绍该芯片的内部组成和工作原理
引脚定义:每个引脚的功能介绍
SPI通信说明:主要介绍芯片的通信方式,这个芯片因为没有设置模式功能,只需要对芯片直接写数据即可,通信方式与我们所使用的74HC595的方式类似
真值对照表:也就是数字量对应的实际电阻值,我这里只截取了一部分,剩下的大家可以自行去参考详细手册
对于要调通这个芯片这些介绍基本满足我们的需求了
芯片模块的快速制作
在芯片商城上买了两片回来调试,芯片购买的费用小伙伴给付了
准备好芯片+转接板
焊接两块是为了防止在使用过程中意外弄坏另一块可以立马补上,确保调试正常进行而不耽误太多时间
焊接好排针,并在供电端加上0.1uF的滤波电容,降低高频供电干扰
这样我们的模块就制作完成了
arduino快速搭建工程
arduino uno 引脚4 -> CLK
arduino uno 引脚5 -> DIN
arduino uno 引脚6 -> CS
arduino uno 引脚5v -> VCC、VREF
arduino uno 引脚GND -> GND、L
arduino uno 引脚A0 -> VRES_OUT
首先用面包板+杜邦线搭好电路
说明:我在这里使用的供电电压和数字电位计参考电压都是使用的5V,相应的输出结果也是在0~5V范围
然后使用arduino自带的库,编写代码,再变动阻值参数,看下输出的实际结果和真值表是否对应的上
数值为0x00时对应的模拟电压输出
数值为0x88时对应的模拟电压输出
数值为0xFF时对应的模拟电压输出
经过验证,在arduino上跑没有问题,接下来我们准备在STM32上去运行
arduino代码部分:
/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the Serial Monitor.
Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/AnalogReadSerial
*/
int CS_Pin = 6;
int CLK_Pin = 4;
int DIN_Pin = 5; //这里定义了那三个脚
// the setup routine runs once when you press reset:
void setup() {
pinMode(CS_Pin,OUTPUT);
pinMode(CLK_Pin,OUTPUT);
pinMode(DIN_Pin,OUTPUT); //让三个脚都是输出状态
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
digitalWrite(CS_Pin,LOW);
shiftOut(DIN_Pin,CLK_Pin,MSBFIRST,0xFF);
digitalWrite(CS_Pin,HIGH);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
float voltage= sensorValue * (5.0 / 1023.0); //换算成电压
// print out the value you read:
Serial.println(voltage,DEC);
delay(100); // delay in between reads for stability
}
STM32搭建工程验证
说明:STM32使用的供电电压和数字电位计参考电压都是3V3,相应的输出结果也是在0~3V3范围
引脚对应关系:
PA4 -> CLK
PA5 -> DIN
PA6 -> CS
3V3 -> VCC、VREF
arduino uno 引脚GND -> GND、L
arduino uno 引脚A0 -> VRES-OUT
开发板+面包板搭建电路
用STM32CubeIDE建立一个工程
配置好PA4、PA5、PA6引脚为输出
生成代码,并添加TPL0501的驱动代码
编译看运行的效果,输入值为0x55
更改输入的数值为0x22,验证是否正确
main函数代码部分:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define TLP0501_DIN_H() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET)
#define TLP0501_DIN_L() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET)
#define TLP0501_CS_H() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET)
#define TLP0501_CS_L() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET)
#define TLP0501_CLK_H() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
#define TLP0501_CLK_L() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void TLP0501_WriteByte( uint8_t data )
{
uint8_t j;
for ( j=8; j>=1; j--)
{
TLP0501_CLK_L();
__NOP();
if(data & 0x80 ){ TLP0501_DIN_H(); }
else { TLP0501_DIN_L(); }
data <<= 1;
TLP0501_CLK_H();
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN 2 */
TLP0501_CS_L();
TLP0501_WriteByte(0x22);
TLP0501_CS_H();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6, GPIO_PIN_RESET);
/*Configure GPIO pins : PA4 PA5 PA6 */
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
总结:
1、这里介绍了众多新IC芯片调试方式中的一种,后期有机会再陆续介绍其他IC或新模块的调试方法。
2、文中只是简单的对芯片进行功能测试,实际项目中还会有移植、驱动的可靠性、稳定性等测试工作 。
3、我们要善于运用手头的工具、arduino等快速验证开发环境;模块的快速验证,特别是在项目开发过程中,时间就是金钱,对每一种工具的熟练掌握也是单片机开发过程中不可或缺的重要技能。
4、硬件调试与软件调试有很大的区别,很多时候是一次性,不可逆转的,不像软件Ctl+Z可以撤销;硬件在使用过程中出现意外损坏情况很正常:焊接不当、意外插错,静电防护不到位等等;我们要善于运用一些项目技巧,权衡时间或花费;这里之所以选择焊接两个芯片模块也是为了防止这种意外的发生而对调试造成不必要的时间耽搁。
单片机项目中使用新IC芯片的调试方法的更多相关文章
- Web项目中JSP页面的一种调试方法与出现的问题 -- SpringMVC架构测试
在前端开发中,尤其是MVC架构多人开发,负责前端的童鞋总是需要做静态页面,再和后台连接前无法使用变量如EL表达式等测试功能,所以本人引入了一个模板jsp数据测试专用文件,专门配置所有的变量,然后在待测 ...
- GDB中应该知道的几个调试方法 来自陈皓
GDB中应该知道的几个调试方法 2011年2月10日陈皓发表评论阅读评论62,325 人阅读 七.八年前写过一篇<用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询 ...
- 【转】GDB中应该知道的几个调试方法
文章来源:http://coolshell.cn/articles/3643.html GDB中应该知道的几个调试方法 2011年02月10日 陈皓 评论 40 条评论 70,776 人阅读 七.八 ...
- 项目中解决实际问题的代码片段-javascript方法,Vue方法(长期更新)
总结项目用到的一些处理方法,用来解决数据处理的一些实际问题,所有方法都可以放在一个公共工具方法里面,实现不限ES5,ES6还有些Vue处理的方法. 都是项目中来的,有代码跟图片展示,长期更新. 1.获 ...
- .NET项目中实现多工程文件共用的方法
一处开发,多处同步编辑使用,并且发布时各个项目均可独立 一.直接编辑项目工程文件 .csproj 具体实现为:编辑 .csproj 文件,在<ItemGroup>中添加新的 <Con ...
- Junit4中的新断言assertThat的使用方法
如果需要是用assertThat需要在项目中引入junit4的jar包.(匹配器和断言方法在junit4的jar包中都能找到,引入就可以了) 下面是常用断言的代码 1 import static or ...
- windows系统下,express构建的node项目中,如何用debug控制调试日志
debug是一款控制日志输出的库,可以在开发调试环境下打开日志输出,生产环境下关闭日志输出.这样比console.log方便多了,console.log只有注释掉才能不输出. debug库还可以根据d ...
- js 自己项目中几种打开或弹出页面的方法
自己项目中,几种打开或弹出页面的方法(部分需要特定环境下) var blnTop = false;//是否在顶层显示 ///动态生成模态窗体(通过字符串生成) ///strModalId:模态窗体ID ...
- x86项目中读取注册表Register数据项的方法
x86项目中使用Registry读取key/value的时候,会出现重定向的问题,解决方法如下: public static string GetMachineGuid() { string guid ...
随机推荐
- 2.Python入门-计算机组成、指令和程序、标识符、变量、数据类型、对象和变量关系、运算符
一.计算机的组成 计算机由两部分组成:硬件 和 软件 硬件包含:键盘.鼠标.显示器.CPU.主板.内存.硬盘 ... -硬件是看的见摸得着的 软件包含:系统软件(windows.macOS.Linux ...
- Docker——Registry搭建私有镜像仓库
前言 在 Docker 中,当我们执行 docker pull xxx 的时候,它实际上是从 registry.hub.docker.com 这个地址去查找,这就是Docker公司为我们提供的公共仓库 ...
- #undef 与 exit(0) 使用
#undef 与 #defined 反,实际使用中较多的是当你需要使用自己定义的标准C里面已经的函数时可以这样操作: exit(0)和exit(1)是系统判断函数是否有正常的退出,一般0表示正常的退 ...
- x轴滚动
#region 设置x轴滚动 XYDiagram diagram = (XYDiagram)chartRoomUserAnalysisHis.Diagram; diagram.Ax ...
- Raft: 一点阅读笔记
前言 如果想要对Raft算法的了解更深入一点的话,仅仅做6.824的Lab和读<In Search of an Understandable Consensus Algorithm>这篇论 ...
- A100 Tensor核心可加速HPC
A100 Tensor核心可加速HPC HPC应用程序的性能需求正在迅速增长.众多科学研究领域的许多应用程序都依赖于双精度(FP64)计算. 为了满足HPC计算快速增长的计算需求,A100 GPU支持 ...
- Linux 2 的 Windows 子系统上发布 CUDA
Linux 2 的 Windows 子系统上发布 CUDA 为响应大众需求,微软 宣布 在 2020 年 5 月的 建造 大会上推出了 建造 ( WSL 2 ) – GPU 加速功能.这一特性为许多计 ...
- 用NVIDIA NsightcComputeRoofline分析加速高性能HPC的应用
用NVIDIA NsightcComputeRoofline分析加速高性能HPC的应用 编写高性能的软件不是一件简单的任务.当有了可以编译和运行的代码之后,当您尝试并理解它在可用硬件上的执行情况时,将 ...
- 1、java数据结构和算法---循环队列
直接上代码: public class CircleArrayQueueLvcai { private int[] array; private int maxSize;//循环队列大小 privat ...
- 最小高度树Java版本(力扣)
最小高度树 给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树. 示例:给定有序数组: [-10,-3,0,5,9],一个可能的答案是:[0,-3,9,-10, ...