三、串口、AD转换

1.串口

串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段, 其重要性不言而喻。
现在基本上所有的 MCU 都会带有串口, STM32 自然也不例外。

而本次实验主要用到串口,rbt6有3个串口,这里我们用串口2;

①、添加库文件

②、 这里我们主要实现的功能是利用串口发送和接受消息;

变量的定义:

u32 TimeDelay=0;

uint8_t RxBuffer[20];        //接收字符存放数组
uint8_t RxCounter=0 ;    //接收到的字符的个数
u8 RXOVER=0;              //接收是否完成标志位

usart配置要用到引脚PA2和PA3

void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef  USART_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	NVIC_Configuration();   
//TX	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽
  
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //RX
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);


  USART_InitStructure.USART_BaudRate = 19200;
  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(USART2, &USART_InitStructure);

  USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
 


  
  USART_Cmd(USART2, ENABLE);

}

中断配置

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

 
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


  
}

 发送字符:因为usart是按字符发送的,而一般我们的消息是字符串,所以需要自定义一个发送函数;

void USART_SendString(u8 *str)
{
u8 index=0;
do
{
USART_SendData(USART2, str[index]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE)==RESET);
index++;

} while(str[index]!=0);


}

 中断服务函数:可在主函数也可在stm32f10x_it.c编写

void USART2_IRQHandler(void)
{
 u8 temp;
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
	USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    temp = USART_ReceiveData(USART2);

    if(temp == 'x'||RxCounter==20)
    {
      RxCounter=0;
	  RXOVER=1;
	   
      USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
    }

	else{
	 RxBuffer[RxCounter]=temp;
	 ++RxCounter;
	
	
	}
  }
  
  
}

这里解释一下

USART中的USART_IT_RXNE,USART_IT_TC,USART_IT_TXE

TXE--写寄存器DR清零
RXNE--读寄存器DR清零,也可软件手动清零
TC--  读/写寄存器DR清零,也可软件手动清零

在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束。
当USART_DR中的数据传送到移位寄存器后,TXE被设置,此时移位寄存器开始向TX信号线按位传输数据,但因为TDR已经变空,程序可以把下一个要发送的字节(操作USART_DR)写入TDR中,而不必等到移位寄存器中所有位发送结束,所有位发送结束时(送出停止位后)硬件会设置TC标志。

你读串口数据时,是装入弹仓,硬件会将数据移到枪膛,这时,RXNE为1,TC为0,STM32硬件的RX脚正在接收数据,但你还可以装入数据到弹仓,装入后,RXNE为0,TC为0.
TX发送完一个数据后,立即将数据从弹仓移入枪膛,这时,RXNE为1,TC为0.
最后TX发送完数据,你又没有装入新数据,这时。RXNE为1,TC为1.

主程序

int main(void)
{
   u8 i;
   USART_Config();
   STM3210B_LCD_Init();
   SysTick_Config(SystemCoreClock/1000);

   Delay_Ms(200);

   USART_SendString("usart send test\r\n");
   USART_SendString("base on ct117e\r\n");

    LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	LCD_DisplayStringLine(Line1," usart receive test ");
	LCD_DisplayStringLine(Line3," Receive:           ");


	LCD_SetTextColor(White);
	LCD_SetBackColor(Blue);
	while(1){
	if(RXOVER==1)
	{
	LCD_ClearLine(Line4);
	LCD_DisplayStringLine(Line4,RxBuffer);
	for(i=0;i<20;i++)
	{
	RxBuffer[i]=0;
	}
	RXOVER=0;

	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

	}
	
	
	}

  
}

 ③、ADC

STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用,
也可以使用双重模式(提高采样率)。 STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。
它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫
描或间断模式执行。 ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正
常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你
的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之
后,规则通道才得以继续转换。
而比赛用的板子有2个adc,其中adc1有18个通道,adc2有16个通道;本次实验主要是为了调节电位器R37输出电压,观察LCD上显示的数值
*           ADC工作模式配置:
*            ADC1 独立模式,单次转换

用到adc1的 通道8(PB0)

首先是adc库文件

adc的配置:

void ADC_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//PB0-ADC channel 8
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	// ADC1 工作模式配置
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    //独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;		//ad单通道
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //单次转换
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	  //转换由软件启动而非外部
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;		   //右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	 ///顺序进行规则转换的初始化外设
	ADC_Init(ADC1, &ADC_InitStructure);

	ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5); // 规则序列的第一个转换  

	ADC_Cmd(ADC1, ENABLE);   
	ADC_ResetCalibration(ADC1);//执行复位校准
	/* Check the end of ADC1 reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);//执行adc校准
	/* Check the end of ADC1 calibration */
	while(ADC_GetCalibrationStatus(ADC1));
}

/*前面讲解过, ADC 的模式非常多, 包括独
立模式,注入同步模式等等,这里我们选择独立模式,所以参数为 ADC_Mode_Independent。
参数 ADC_ScanConvMode 用来设置是否开启扫描模式, 因为是单次转换,这里我们选择不开
启值 DISABLE 即可。
参数 ADC_ContinuousConvMode 用来设置是否开启连续转换模式,因为是单次转换模式,所以
我们选择不开启连续转换模式, DISABLE 即可。
参数 ADC_ExternalTrigConv 是用来设置启动规则转换组转换的外部事件,这里我们选择软件触
发,选择值为 ADC_ExternalTrigConv_None 即可。
参数 DataAlign 用来设置 ADC 数据对齐方式是左对齐还是右对齐,这里我们选择右对齐方式
ADC_DataAlign_Right。
参数 ADC_NbrOfChannel 用来设置规则序列的长度,这里我们是单次转换,所以值为 1 即可。

在上面的校准完成之后, ADC 就算准备好了。接下来我们要做的就是设置规则序列 1 里面
的通道,采样顺序, 以及通道的采样周期, 然后启动 ADC 转换。在转换结束后,读取 ADC 转
换结果值就是了。 这里设置规则序列通道以及采样周期的函数是:
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,
uint8_t Rank, uint8_t ADC_SampleTime);
我们这里是规则序列中的第 1 个转换,同时采样周期为 13.5,所以设置为:
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5); // 规则序列的第一个转换 
*/

数据读取函数

float Read_ADC(void)
{
float ADC_VALUE;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

Delay_Ms(5);

ADC_VALUE=(ADC_GetConversionValue(ADC1)*3.3)/0XFFF;

return 	ADC_VALUE;


}

 软件开启 ADC 转换的方法是:
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的 ADC1 的软件转换启动功能
开启转换之后,就可以获取转换 ADC 转换结果数据, 方法是:
ADC_GetConversionValue(ADC1);

主函数:

int main(void)
{
float adc_temp,tem_temp;
u8 string[20];
u8 string1[20];

 SysTick_Config(SystemCoreClock/1000);
 ADC_Config();


    STM3210B_LCD_Init();
	LCD_Clear(White);
	LCD_SetTextColor(White);
	LCD_SetBackColor(Blue);
	LCD_ClearLine(Line0);
	LCD_ClearLine(Line1);
	LCD_ClearLine(Line2);
	LCD_ClearLine(Line3);
	LCD_ClearLine(Line4);

	LCD_DisplayStringLine(Line1,"      ADC TEST      ");
	LCD_DisplayStringLine(Line3,"  PB0-ADC channel 8 ");

	LCD_SetTextColor(Blue);
	LCD_SetBackColor(White);
  
  while (1)
  {
  Delay_Ms(200);
  adc_temp=Read_ADC();
  tem_temp=(1430-adc_temp*1000)/4.3+25;
  sprintf(string,"%s%.3f","ADC Value ",adc_temp);
  sprintf(string1,"%s%.3f","Tem Value:",tem_temp);
  
  LCD_DisplayStringLine(Line7,string);
  LCD_DisplayStringLine(Line9,string1);
  }
}

④、内部温度传感器

与上述配置大同小异,由引脚图,需该改通道为16同时还有计算方法

void ADC_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
// 	RCC_ADCCLKConfig(RCC_PCLK2_Div4); 
	
	// ADC1 工作模式配置
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //单次转换
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);

	ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5);    
	ADC_TempSensorVrefintCmd(ENABLE);  //使能温度传感器
	
	ADC_Cmd(ADC1, ENABLE);   
	ADC_ResetCalibration(ADC1);
	/* Check the end of ADC1 reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	/* Check the end of ADC1 calibration */
	while(ADC_GetCalibrationStatus(ADC1));
}

 主函数:

int main(void)
{
float  adc_temp,tem_temp;
u8 string[20];


 SysTick_Config(SystemCoreClock/1000);
 ADC_Config();


    STM3210B_LCD_Init();
	LCD_Clear(White);
	LCD_SetTextColor(White);
	LCD_SetBackColor(Blue);
	LCD_ClearLine(Line0);
	LCD_ClearLine(Line1);
	LCD_ClearLine(Line2);
	LCD_ClearLine(Line3);
	LCD_ClearLine(Line4);

	LCD_DisplayStringLine(Line1,"      Tem TEST      ");
	LCD_DisplayStringLine(Line3,"   channel 16");

	LCD_SetTextColor(Blue);
	LCD_SetBackColor(White);
  
  while (1)
  {
  Delay_Ms(200);
  adc_temp=Read_ADC();
  tem_temp=(1430-adc_temp*1000)/4.3+25;

  sprintf(string,"%s%.3f","Tem Value:",tem_temp);
  
  LCD_DisplayStringLine(Line7,string);
 
  }
}
发布了48 篇原创文章 · 获赞 129 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qqGHJ/article/details/86670100
ad