本文简单介绍了STM32F103C8,通过DMA方式读取ADC并通过串口中断向电脑端打印出当前电源ADC的值。
现在先将设计过程的主要步骤介绍如下:
1,串口配置
2,中断配置
3,DMA配置
4,ADC配置
5,中断服务函数
6,主函数
先总结下博主在这次基础设计中犯的错误,在中断初始化函数中,没有将中断通道使能,导致电脑端没有接收到数据,发现后就去检查串口初始化函数了,结果没有发现错误,而是检查了一遍代码才发现错误。发现串口无法工作后,先核查初始化函数,如果问题没有解决,第二步,如果是串口中断方式,接下来检查,中断初始化函数,如果是串口查询方式,接下来检查主函数的串口查询代码。
接下来详细介绍各个步骤:
1,串口配置
- void usart_init(void)
- {
- GPIO_InitTypeDef GPIO_usart;定义GPIO结构体
- USART_InitTypeDef USART_usart;定义串口结构体
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1 ,ENABLE);使能外设时钟
-
- GPIO_usart.GPIO_Pin = GPIO_Pin_9;
- GPIO_usart.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_usart);配置发送口
-
- GPIO_usart.GPIO_Pin = GPIO_Pin_10;
- GPIO_usart.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_usart);配置接受口
-
- USART_usart.USART_BaudRate = 115200;设置传输波特率
- USART_usart.USART_WordLength = USART_WordLength_8b;设置串口发送字长
- USART_usart.USART_StopBits = USART_StopBits_1;设置停止位
- USART_usart.USART_Parity = USART_Parity_No;不进行奇偶校验
- USART_usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;硬件流使能
- USART_usart.USART_Mode = USART_Mode_Tx;设置为发送模式
- USART_Init(USART1,&USART_usart);初始化串口寄存器
-
- USART_Cmd(USART1,ENABLE);串口使能
- USART_ClearFlag(USART1,USART_FLAG_TC);清除已发送位,防止第一位发不出去
- }
复制代码
2,中断配置
- void nvic_init(void)
- {
- NVIC_InitTypeDef nvic_usart;定义中断结构体
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);设置中断分组
- nvic_usart.NVIC_IRQChannel = USART1_IRQn;制定中断服务函数通道
- nvic_usart.NVIC_IRQChannelPreemptionPriority = 1;抢占优先级1
- nvic_usart.NVIC_IRQChannelSubPriority = 0;子优先级0
- nvic_usart.NVIC_IRQChannelCmd = ENABLE;通道使能
- NVIC_Init(&nvic_usart);中断寄存器初始化
- }
复制代码
3,DMA配置
- void dma_init(void)
- {
- DMA_InitTypeDef dma;定义DMA结构体
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);打开时钟
-
- DMA_DeInit(DMA1_Channel1);现将DMA,通道1寄存器复位
- dma.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;设置外设地址
- dma.DMA_MemoryBaseAddr = (uint32_t)ADC_Value;设置存储器地址
- dma.DMA_DIR = DMA_DIR_PeripheralSRC;设置传输方向为 外设到存储器
- dma.DMA_BufferSize = 2;数据缓冲为设置为2
- dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;外设地址固定
- dma.DMA_MemoryInc = DMA_MemoryInc_Enable;寄存器地址自增
- dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;外设数据位宽度半字
- dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;存储器数据位宽度半字
- dma.DMA_Mode = DMA_Mode_Circular;DMA工作在循环模式
- dma.DMA_Priority = DMA_Priority_High;DMA通道为高优先级
- dma.DMA_M2M = DMA_M2M_Disable;内存到内存传输使能
- DMA_Init(DMA1_Channel1,&dma);初始化DMA寄存器
-
- //DMA_Cmd(DMA1_Channel1,ENABLE);使能通道1 (笔者把这句放到主函数中了,在这里写也行,只不过是笔者认为放到主函数中便于理解)
- }
复制代码
4,adc配置
- void adc_init(void)
- {
- ADC_InitTypeDef adc;定义adc结构体
- GPIO_InitTypeDef adc_gpio;定义GPIO结构体
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB,ENABLE);使能外设
-
- adc_gpio.GPIO_Pin = GPIO_Pin_1;
- adc_gpio.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOB,&adc_gpio);使能ADC的测试通道
-
- ADC_DeInit(ADC1);复位ADC1寄存器
- ADC_TempSensorVrefintCmd(ENABLE);使能内部参照电压
- adc.ADC_Mode = ADC_Mode_Independent;ADC工作在独立模式
- adc.ADC_ScanConvMode = ENABLE;使用扫描模式
- adc.ADC_ContinuousConvMode = ENABLE;使用连续转换模式
- adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;不使用外部触发工作模式
- adc.ADC_DataAlign = ADC_DataAlign_Right;数据设置为右对齐
- adc.ADC_NbrOfChannel = 2;两个转换通道
-
- ADC_Init(ADC1,&adc);初始化寄存器
-
- ADC_RegularChannelConfig(ADC1,ADC_Channel_9,1,ADC_SampleTime_239Cycles5);对通道9采样(电源电压)
- ADC_RegularChannelConfig(ADC1,ADC_Channel_17,2,ADC_SampleTime_239Cycles5);对通道11采样(参考电压)
-
- //ADC_DMACmd(ADC1,ENABLE);ADC 的DMA通道使能
-
- //ADC_Cmd(ADC1,ENABLE);ADC使能
-
- //ADC_ResetCalibration(ADC1);复位ADC1的校准寄存器
- //while(ADC_GetResetCalibrationStatus(ADC1));等待复位完成
-
- //ADC_StartCalibration(ADC1);开始ADC1校准
- //while(ADC_GetCalibrationStatus(ADC1));等待校准完成
-
- //ADC_SoftwareStartConvCmd(ADC1,ENABLE);ADC1的软件转换使能(注:这些注释的部分我放到主函数里了,放在这里也行,只不过,我感觉我那样便于理解)
- }
复制代码
5,中断服务函数
- void USART1_IRQHandler(void)
- {
- if(USART1->SR & USART_SR_TC)判断是否能发送数据
- {
- USART1->DR = TxBuff[TxCount++];笔者将转换到的电压值存到TxBuff[0]中了
- if(TxCount == Count)等到传完一次数据,就退出中断
- {
- USART1->CR1 &= ~USART_CR1_TXEIE;
- }
- }
- }
复制代码
6,主函数
- int main()
- {
- usart_init();串口初始化
- nvic_init();中断初始化
- dma_init();DMA初始化
- adc_init();ADC初始化
- DMA_Cmd(DMA1_Channel1,ENABLE);//见上文
- ADC_DMACmd(ADC1,ENABLE);同上
-
- ADC_Cmd(ADC1,ENABLE);同上
-
- ADC_ResetCalibration(ADC1);同上
- while(ADC_GetResetCalibrationStatus(ADC1));同上
-
- ADC_StartCalibration(ADC1);同上
- while(ADC_GetCalibrationStatus(ADC1));同上
-
- ADC_SoftwareStartConvCmd(ADC1,ENABLE);同上
- while(1)循环打印电压值
- {
- Voltage_Printf();用于打印电压
- //PrintString("\r\nprint data!!\r\n");
- delay(1000);延时
- }
复制代码
- void Voltage_Printf(void)
- {
- Battery = (uint16_t)(2.0f *ADC_Value[0] / ADC_Value[1] *1.2f * 100);根据参考电压按比例计算电源电压
- PrintString("\r\n当前电压值的一百倍:");
- PrintU16(Battery);
- PrintString("V");
- }
复制代码
下面粘贴完整代码
- #include<stm32f10x.h>
-
- uint16_t ADC_Value[2];
- static uint16_t Battery=0;
- uint8_t TxCount = 0;
- uint8_t Count = 0;
- static uint8_t TxBuff[250];
- volatile uint8_t RxBuffer[50];
-
- void delay(uint32_t n)
- {
- int i,j;
- for(i=0;i<n;i++)
- for(j=0;j<8500;j++);
- }
-
- void usart_init(void)
- {
- GPIO_InitTypeDef GPIO_usart;
- USART_InitTypeDef USART_usart;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1 ,ENABLE);
-
- GPIO_usart.GPIO_Pin = GPIO_Pin_9;
- GPIO_usart.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_usart);
-
- GPIO_usart.GPIO_Pin = GPIO_Pin_10;
- GPIO_usart.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_usart);
-
- USART_usart.USART_BaudRate = 115200;
- USART_usart.USART_WordLength = USART_WordLength_8b;
- USART_usart.USART_StopBits = USART_StopBits_1;
- USART_usart.USART_Parity = USART_Parity_No;
- USART_usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_usart.USART_Mode = USART_Mode_Tx;
- USART_Init(USART1,&USART_usart);
-
- USART_Cmd(USART1,ENABLE);
- USART_ClearFlag(USART1,USART_FLAG_TC);
- }
-
- void nvic_init(void)
- {
- NVIC_InitTypeDef nvic_usart;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- nvic_usart.NVIC_IRQChannel = USART1_IRQn;
- nvic_usart.NVIC_IRQChannelPreemptionPriority = 1;
- nvic_usart.NVIC_IRQChannelSubPriority = 0;
- nvic_usart.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&nvic_usart);
- }
-
- void dma_init(void)
- {
- DMA_InitTypeDef dma;
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
-
- DMA_DeInit(DMA1_Channel1);
- dma.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;
- dma.DMA_MemoryBaseAddr = (uint32_t)ADC_Value;
- dma.DMA_DIR = DMA_DIR_PeripheralSRC;
- dma.DMA_BufferSize = 2;
- dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
- dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
- dma.DMA_Mode = DMA_Mode_Circular;
- dma.DMA_Priority = DMA_Priority_High;
- dma.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel1,&dma);
-
- //DMA_Cmd(DMA1_Channel1,ENABLE);
- }
- void adc_init(void)
- {
- ADC_InitTypeDef adc;
- GPIO_InitTypeDef adc_gpio;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB,ENABLE);
-
- adc_gpio.GPIO_Pin = GPIO_Pin_1;
- adc_gpio.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOB,&adc_gpio);
-
- ADC_DeInit(ADC1);
- ADC_TempSensorVrefintCmd(ENABLE);
- adc.ADC_Mode = ADC_Mode_Independent;
- adc.ADC_ScanConvMode = ENABLE;
- adc.ADC_ContinuousConvMode = ENABLE;
- adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
- adc.ADC_DataAlign = ADC_DataAlign_Right;
- adc.ADC_NbrOfChannel = 2;
-
- ADC_Init(ADC1,&adc);
-
- ADC_RegularChannelConfig(ADC1,ADC_Channel_9,1,ADC_SampleTime_239Cycles5);
- ADC_RegularChannelConfig(ADC1,ADC_Channel_17,2,ADC_SampleTime_239Cycles5);
-
- //ADC_DMACmd(ADC1,ENABLE);
-
- //ADC_Cmd(ADC1,ENABLE);
-
- //ADC_ResetCalibration(ADC1);
- //while(ADC_GetResetCalibrationStatus(ADC1));
-
- //ADC_StartCalibration(ADC1);
- //while(ADC_GetCalibrationStatus(ADC1));
-
- //ADC_SoftwareStartConvCmd(ADC1,ENABLE);
- }
- void PrintHexU8(uint8_t data)
- {
- TxBuff[Count++] = data;
- if(!(USART1->CR1 & USART_CR1_TXEIE))
- USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
- }
-
- void PrintString(uint8_t *s)
- {
- uint8_t *p;
- p=s;
- while(*p!= '\0')
- {
- PrintHexU8(*p);
- p++;
- }
- }
-
- void PrintU16(uint16_t num)
- {
- uint8_t w5,w4,w3,w2,w1;
- w5 = num % 100000/10000;
- w4 = num % 10000/1000;
- w3 = num % 1000/100;
- w2 = num % 100/10;
- w1 = num % 10;
- PrintHexU8('0' + w5);
- PrintHexU8('0' + w4);
- PrintHexU8('0' + w3);
- PrintHexU8('0' + w2);
- PrintHexU8('0' + w1);
- }
-
- void Voltage_Printf(void)
- {
- Battery = (uint16_t)(2.0f *ADC_Value[0] / ADC_Value[1] *1.2f * 100);
- PrintString("\r\nµ±Ç°µç³Øµçѹֵһ°Ù±¶£º");
- PrintU16(Battery);
- PrintString("V");
- }
- int main()
- {
- usart_init();
- nvic_init();
- dma_init();
- adc_init();
- DMA_Cmd(DMA1_Channel1,ENABLE);
- ADC_DMACmd(ADC1,ENABLE);
-
- ADC_Cmd(ADC1,ENABLE);
-
- ADC_ResetCalibration(ADC1);
- while(ADC_GetResetCalibrationStatus(ADC1));
-
- ADC_StartCalibration(ADC1);
- while(ADC_GetCalibrationStatus(ADC1));
-
- ADC_SoftwareStartConvCmd(ADC1,ENABLE);
- while(1)
- {
- Voltage_Printf();
- //PrintString("\r\nprint data!!\r\n");
- delay(1000);
- }
- }
-
- void USART1_IRQHandler(void)
- {
- if(USART1->SR & USART_SR_TC)
- {
- USART1->DR = TxBuff[TxCount++];
- if(TxCount == Count)
- {
- USART1->CR1 &= ~USART_CR1_TXEIE;
- }
- }
-
- if(USART1->SR & USART_SR_RXNE)
- {
- volatile int8_t com_data;
- com_data = USART1->DR;
- }
- }
复制代码
————————————————
版权声明:家安
|