使用串口调试助手调试keil5软件的代码时,通过printf函数可以发送字符串,发送ADC采集的动态的数时却是乱码是什么原因
时间: 2024-02-15 13:05:55 浏览: 39
这可能是由于printf函数发送的字符串与ADC采集的数值类型不同所导致的。printf函数默认将数值以ASCII码的形式发送,而ADC采集的数值可能是16位或32位的二进制数值,如果直接将其传递给printf函数,则会导致乱码的出现。
为了解决这个问题,可以将ADC采集的数值转换为字符串形式,然后再通过printf函数发送。可以使用库函数sprintf来实现这个功能。例如,可以使用以下代码将ADC采集的数值转换为字符串:
```
char buffer[20];
sprintf(buffer, "%d", adc_value);
printf("%s", buffer);
```
其中,adc_value为ADC采集的数值,%d表示将其转换为10进制整数形式,buffer为保存转换结果的数组。通过这种方式,就可以将ADC采集的数值以字符串形式发送,避免了乱码的问题。
相关问题
使用ADC1,通道1(PA1)引脚采集模拟电压,定时1s将数据通过串口发送到串口调试助手上
好的,这是一个简单的STM32单片机应用程序,可以使用STM32CubeMX和Keil工具链进行开发。下面是大致的实现步骤:
1. 配置ADC1模块和PA1引脚为模拟输入模式。可以使用STM32CubeMX进行配置,设置ADC1为单次转换模式,转换通道为PA1。
2. 配置串口模块,设置波特率为需要的值,并使能发送功能。同样可以使用STM32CubeMX进行配置。
3. 配置定时器,设置为1s定时器,使其定时中断触发。同样可以使用STM32CubeMX进行配置。
4. 在主函数中,初始化以上模块,并在while循环中不断进行ADC转换、串口发送和延时操作。具体实现如下:
```
#include "stm32f1xx_hal.h"
#include "stdio.h"
/* ADC1定义 */
ADC_HandleTypeDef hadc1;
/* 串口定义 */
UART_HandleTypeDef huart1;
/* 定时器定义 */
TIM_HandleTypeDef htim2;
/* 定义变量存储ADC采样值 */
uint32_t adc_value;
/* 函数定义 */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_ADC1_Init(void);
int main(void)
{
/* MCU配置 */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
MX_ADC1_Init();
/* 启动定时器 */
HAL_TIM_Base_Start_IT(&htim2);
while (1)
{
/* 启动ADC转换 */
HAL_ADC_Start(&hadc1);
/* 等待转换完成 */
HAL_ADC_PollForConversion(&hadc1, 100);
/* 获取采样值 */
adc_value = HAL_ADC_GetValue(&hadc1);
/* 将采样值转换为电压值,公式为 V = ADC采样值/4096 * 3.3V */
float voltage = (float)adc_value / 4096 * 3.3;
/* 将电压值转换为字符串 */
char str[10];
sprintf(str, "%.2fV\n", voltage);
/* 通过串口发送电压值 */
HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000);
/* 延时1s */
HAL_Delay(1000);
}
}
/* 系统时钟初始化 */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* GPIO初始化 */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO时钟使能 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* PA1模拟输入 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* 定时器初始化 */
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
/* 定时器时钟使能 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 基本定时器2初始化 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7200 - 1; /* 1ms定时 */
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; /* 定时1s */
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
/* 定时器2配置为中断模式 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* 串口初始化 */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/* ADC1初始化 */
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/* ADC时钟使能 */
__HAL_RCC_ADC1_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
/* 错误处理函数 */
void Error_Handler(void)
{
while (1)
{
}
}
/* 定时器中断处理函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == &htim2)
{
/* 在定时器中断中启动ADC转换 */
HAL_ADC_Start_IT(&hadc1);
}
}
/* ADC转换完成中断处理函数 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
/* 不做任何操作,ADC采样值在主函数中获取 */
}
```
注意:以上代码仅供参考,具体实现可能需要根据实际情况进行修改。
stm32f103c8t6产生200Hz定时器中断,并在中断服务函数中采集三路ADC信号并通过115200波特率串口发送adc读数keil代码
以下是基于Keil MDK开发环境的示例代码,实现了STM32F103C8T6产生200Hz定时器中断,并在中断服务函数中采集三路ADC信号并通过115200波特率串口发送ADC读数。
```c
#include "stm32f10x.h"
#include "stdio.h"
#define ADC1_DR_Address ((u32)0x4001244C) // ADC1数据寄存器地址
volatile u16 ADC_Value[3]; // 存放ADC采样值
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
// USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART1_RX GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART1 初始化设置
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 支持发送和接收
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); // 使能USART1
}
void Timer2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = 5000 - 1; // 定时器重载值,计算公式为:Tout = ((arr+1)*(psc+1))/Tclk,Tout = 1/200Hz
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 定时器预分频值,计算公式为:Tclk = HCLK/(psc+1),Tclk = 1MHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频因子
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 使能定时器2更新中断
TIM_Cmd(TIM2, ENABLE); // 使能定时器2
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 定时器2中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC
}
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // 使能GPIOA和ADC1时钟
// PA0、PA1、PA2模拟输入配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC1和ADC2工作在独立模式下
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 开启扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不开启外部触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC转换数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 3; // 要转换的通道数
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 配置ADC1的第1个规则通道为PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); // 配置ADC1的第2个规则通道为PA1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); // 配置ADC1的第3个规则通道为PA2
ADC_DMACmd(ADC1, ENABLE); // 开启ADC1的DMA传输
ADC_Cmd(ADC1, ENABLE); // 使能ADC1
ADC_ResetCalibration(ADC1); // 复位ADC1校准寄存器
while (ADC_GetResetCalibrationStatus(ADC1)); // 等待ADC1校准寄存器复位完成
ADC_StartCalibration(ADC1); // 开始ADC1校准
while (ADC_GetCalibrationStatus(ADC1)); // 等待ADC1校准完成
}
void DMA1_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA1时钟
DMA_DeInit(DMA1_Channel1); // 复位DMA1通道1
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; // 指定DMA传输的外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_Value; // 指定DMA传输的内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // DMA传输方向:外设->内存
DMA_InitStructure.DMA_BufferSize = 3; // DMA传输数据量,即ADC采样通道数
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 禁止外设地址增量
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 允许内存地址增量
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设数据位宽为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 内存数据位宽为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 循环传输模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 关闭内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); // 初始化DMA1通道1
DMA_Cmd(DMA1_Channel1, ENABLE); // 使能DMA1通道1
}
void USART_SendByte(USART_TypeDef* USARTx, uint8_t byte)
{
USART_SendData(USARTx, (uint8_t)byte);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); // 等待发送完成
}
void USART_SendString(USART_TypeDef* USARTx, char* str)
{
while (*str)
{
USART_SendByte(USARTx, *str++);
}
}
int fputc(int ch, FILE* f)
{
USART_SendByte(USART1, ch);
return ch;
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
DMA_Cmd(DMA1_Channel1, DISABLE); // 关闭DMA传输
USART_SendString(USART1, "ADC1_Value: ");
printf("%d %d %d\r\n", ADC_Value[0], ADC_Value[1], ADC_Value[2]); // 通过串口发送ADC采样值
DMA_SetCurrDataCounter(DMA1_Channel1, 3); // 设置DMA数据传输量
DMA_Cmd(DMA1_Channel1, ENABLE); // 重新打开DMA传输
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除定时器2更新中断标志
}
}
int main(void)
{
USART1_Init();
Timer2_Init();
ADC1_Init();
DMA1_Init();
while (1);
}
```