本帖最后由 x1816 于 2023-10-23 09:57 编辑
电路分析
LaunchPad板载的热敏电阻是10k的线性热敏电阻(PTC),与10k的定值电阻串联分压。室温下输出电压大约是1.6V。通过J1跳线可以直接输出到MSPM0L1306的PA. 15。
软件设计
使用adc_to_uart模板,可以将adc转换结果输出到串口。
使用SysConfig工具,将ADC12的输入通道设定为Channel 9,界面上会自动提示Pin为PA15。
也可以点击界面右上角的Device View,直接查看Pin的分配情况。
改用printf()函数发送数据:
将ADC值转换为温度的代码可以直接从OOBE中摘录,或者参考热敏电阻的文档。
用手指放在热敏电阻附近的PCB上,捂热一会后,温度明显上升。
版图设计
热敏电阻(RT1)在开发板下部中间位置。可以看到PCB此处有镂空的狭缝设计,将热敏电阻放置在“孤岛”上。这样做可以将PCB其余部分的发热对温度测量影响降低到最低,从而使热敏电阻可以更准确地测量环境温度。
小结
得益于合适的样例程序和SysConfig,对MSPM0的ADC、UART等外设编程十分容易。这样我们就不需要手写大量繁琐的配置代码,也不需要反复查阅参考手册,只需要专注于业务逻辑即可。
完整代码
C程序
#include "stdio.h"
#include <math.h>
#include "ti_msp_dl_config.h"
volatile bool gCheckADC;
volatile uint16_t gADCResult;
volatile float temperature;
float VBias = 3.30; // set the VBIAS voltage
// set the number of bits based on you ADC (2^# of ADC Bit Value)
unsigned int ADC_BITS = 4096;
float VTEMP = 0; // set up the variable for the measured voltage
float THRM_TEMP = 0; // setup the variable for the calculated temperature
float thermistor_calc_temperature(uint16_t raw_ADC) {
// THRM calculations via regression
// Copied from TI Thermistor Design Tool Excel Doc
float VTEMP = 0.0;
float THRM_ADC = raw_ADC;
float THRM_A0 = -4.232811E+02;
float THRM_A1 = 4.728797E+02;
float THRM_A2 = -1.988841E+02;
float THRM_A3 = 4.869521E+01;
float THRM_A4 = -1.158754E+00;
VTEMP = (VBias / ADC_BITS) * THRM_ADC; // calculate volts per bit then
// multiply that times the ADV value
THRM_TEMP = (THRM_A4 * powf(VTEMP, 4)) + (THRM_A3 * powf(VTEMP, 3)) +
(THRM_A2 * powf(VTEMP, 2)) + (THRM_A1 * VTEMP) +
THRM_A0; // 4th order regression to get temperature
return THRM_TEMP;
}
int main(void) {
SYSCFG_DL_init();
NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
gCheckADC = false;
while (1) {
DL_ADC12_startConversion(ADC12_0_INST);
while (false == gCheckADC) {
__WFE();
}
/*
* UART is 8 bits and the ADC result is 16 bits
* Split the ADC result into 2 then send via UART.
*/
gADCResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
// uint8_t lowbyte = (uint8_t)(gADCResult & 0xFF);
// uint8_t highbyte = (uint8_t)((gADCResult >> 8) & 0xFF);
temperature = thermistor_calc_temperature(gADCResult);
printf("ADC=%d, temperature=%f\n", gADCResult, temperature);
// DL_UART_Main_transmitData(UART_0_INST, highbyte);
// DL_UART_Main_transmitData(UART_0_INST, lowbyte);
gCheckADC = false;
DL_ADC12_enableConversions(ADC12_0_INST);
}
}
void ADC12_0_INST_IRQHandler(void) {
switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
gCheckADC = true;
break;
default:
break;
}
}
SysConfig参考代码
**
* These arguments were used when this file was generated. They will be automatically applied on subsequent loads
* via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
* @cliArgs --device "MSPM0L130X" --package "VQFN-32(RHB)" --part "Default" --product "mspm0_sdk@1.20.00.06"
* @versions {"tool":"1.18.0+3266"}
*/
/**
* Import the modules used in this configuration.
*/
const ADC12 = scripting.addModule("/ti/driverlib/ADC12", {}, false);
const ADC121 = ADC12.addInstance();
const Board = scripting.addModule("/ti/driverlib/Board");
const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
const UART = scripting.addModule("/ti/driverlib/UART", {}, false);
const UART1 = UART.addInstance();
/**
* Write custom configuration values to the imported modules.
*/
ADC121.$name = "ADC12_0";
ADC121.enabledInterrupts = ["DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED"];
ADC121.sampleTime0 = "125 us";
ADC121.sampClkSrc = "DL_ADC12_CLOCK_ULPCLK";
ADC121.sampClkDiv = "DL_ADC12_CLOCK_DIVIDE_8";
ADC121.adcMem0chansel = "DL_ADC12_INPUT_CHAN_9";
ADC121.peripheral.$assign = "ADC0";
ADC121.adcPin9Config.$name = "ti_driverlib_gpio_GPIOPinGeneric0";
UART1.$name = "UART_0";
UART1.enableFIFO = true;
UART1.direction = "TX";
UART1.rxFifoThreshold = "DL_UART_RX_FIFO_LEVEL_ONE_ENTRY";
UART1.targetBaudRate = 115200;
UART1.peripheral.$assign = "UART0";
UART1.peripheral.txPin.$assign = "PA8";
UART1.txPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric1";
/**
* Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
* version of the tool will not impact the pinmux you originally saw. These lines can be completely deleted in order to
* re-solve from scratch.
*/
ADC121.peripheral.adcPin9.$suggestSolution = "PA15";
Board.peripheral.$suggestSolution = "DEBUGSS";
Board.peripheral.swclkPin.$suggestSolution = "PA20";
Board.peripheral.swdioPin.$suggestSolution = "PA19";
SYSCTL.peripheral.$suggestSolution = "SYSCTL";