单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 387|回复: 1
收起左侧

LABVIEW上位机+STM32内部温度传感器源程序

[复制链接]
胡大 发表于 2019-7-17 19:57 | 显示全部楼层 |阅读模式
0.jpg
1、打开电脑的“控制面板” -->“字体”,把“数码管字体”文件夹中的两个文件,复制到“字体”中

2、重新打开main.vi,就可以在您的字体设置栏找到NI7SEG字体了

3、本labview采集程序采用了自动识别单片机串口技术,用户不必手动选择串口

4、本程序可以测量STM32芯片内部的温度。如果您用手按住开发板上的STM32芯片,可以看到labview上显示的温度在增加

5、本实验的采样率是:10/秒,即labview可以在100ms之内处理完一个数据。如果用户的采样率加大,请采用labview生产者/消费者结构

单片机源程序如下:

  1. /*****************************************************************
  2. *
  3. * 文件名: main.c
  4. * 内容简述: 本程序演示了STM32内部温度传感器的ADC(非DMA)以及过采样技术的使用
  5.             采用RS485通信方式。可使用RS232转RS485转换器,PC机上的LabVIEW上位机仍然是串口方式,不需改动
  6. *
  7. *
  8. ******************************************************************/
  9. #include "stm32f10x.h"
  10. #include <stdio.h>

  11. u8 ah,al,comm = 0;
  12. u16 ad;
  13. u32 tempu32 = 0;

  14. u8 gototime = 0;

  15. /*************************************************
  16. 函数: void RCC_Configuration(void)
  17. 功能: 复位和时钟控制 配置
  18. 参数: 无
  19. 返回: 无
  20. **************************************************/
  21. void RCC_Configuration(void)
  22. {
  23.   ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  24.   RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  25.   RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  26.   HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  27.   if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  28.   {
  29.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
  30.     FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
  31.              
  32.     RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
  33.     RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
  34.     RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
  35.          
  36.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
  37.     RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
  38.    
  39.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
  40.     {
  41.     }
  42.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
  43.     while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
  44.     {
  45.     }
  46.   }
  47.   
  48.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOF | RCC_APB2Periph_AFIO, ENABLE);  //允许GPIOB、GPIOF、AFIO时钟
  49. }

  50. /*******************************************************************************
  51.         函数名:ADC_Configuration
  52.         输  入:
  53.         输  出:
  54.         功能说明:配置ADC
  55. */
  56. static void ADC_Configuration(void)
  57. {
  58.         ADC_InitTypeDef ADC_InitStructure;

  59.     /* 使能 ADC1 and GPIOC clock */
  60.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  61.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);              //72M/6=12,ADC最大时间不能超过14M

  62.         /* 配置ADC1, 不用DMA, 用软件自己触发 */
  63.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                 //ADC1工作模式:独立模式
  64.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;                         //单通道模式
  65.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                 //单次转换
  66.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;          //转换由软件而不是外部触发启动
  67.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;         //ADC1数据右对齐
  68.         ADC_InitStructure.ADC_NbrOfChannel = 1;           //顺序进行规则转换的ADC通道的数目
  69.         ADC_Init(ADC1, &ADC_InitStructure);                   //根据ADC_InitStruct中指定的参数,初始化外设ADC1的寄存器

  70.         /* ADC1 regular channel16 configuration */
  71.         ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5);        //ADC1,ADC通道16,规则采样顺序值为1,采样时间为55.5周期

  72.     ADC_TempSensorVrefintCmd(ENABLE);                   //ADC内置温度传感器使能(要使用片内温度传感器,切记要开启它)

  73.         /* Enable ADC1 */
  74.         ADC_Cmd(ADC1, ENABLE);                  //使能ADC1

  75.         /* Enable ADC1 reset calibaration register */
  76.         ADC_ResetCalibration(ADC1);                                                //重置ADC1的校准寄存器
  77.         /* Check the end of ADC1 reset calibration register */
  78.         while(ADC_GetResetCalibrationStatus(ADC1));                //获取ADC1重置校准寄存器的状态,设置状态则等待

  79.         /* Start ADC1 calibaration */
  80.         ADC_StartCalibration(ADC1);                                        //开始ADC1的校准状态
  81.         /* Check the end of ADC1 calibration */
  82.         while(ADC_GetCalibrationStatus(ADC1));                //等待校准完成

  83.         /* Start ADC1 Software Conversion */
  84.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能ADC1的软件转换启动功能
  85. }

  86. /*******************************************************************************
  87. * Function Name   : NVIC_Configuration
  88. * Description        : Configures NVIC and Vector Table base location.
  89. * Input                    : None
  90. * Output                 : None
  91. * Return                 : None
  92. *******************************************************************************/
  93. void NVIC_Configuration(void)
  94. {
  95.    NVIC_InitTypeDef NVIC_InitStructure;
  96.   
  97.    /* Set the Vector Table base location at 0x08000000 */
  98.    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  99.   
  100.    /* Configure the NVIC Preemption Priority Bits */  
  101.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  102.   
  103.    /* Enable the USART1 Interrupt */
  104.    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  105.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  106.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  107.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  108.    NVIC_Init(&NVIC_InitStructure);

  109.   //配置TIM2中断
  110.   NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  111.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  112.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  113.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  114.   NVIC_Init(&NVIC_InitStructure);
  115. }

  116. /*******************************************************************************
  117.         函数名:USART3_Configuration
  118.         输  入:
  119.         输  出:
  120.         功能说明:
  121.         初始化串口硬件设备,启用中断
  122.         配置步骤:
  123.         (1)打开GPIO和USART的时钟
  124.         (2)设置USART3两个管脚GPIO模式
  125.         (3)配置USART3数据格式、波特率等参数
  126.         (4)使能USART3接收中断功能
  127.         (5)最后使能USART3功能
  128. */
  129. void USART3_Configuration(void)
  130. {
  131.         GPIO_InitTypeDef GPIO_InitStructure;
  132.         USART_InitTypeDef USART_InitStructure;

  133.         /* 第1步:打开GPIO和USART3部件的时钟 */
  134.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
  135.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  136.         /* 第2步:将USART3 Tx的GPIO配置为推挽复用模式 */
  137.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  138.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  139.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  140.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  141.         /* 第3步:将USART3 Rx的GPIO配置为浮空输入模式
  142.                 由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
  143.                 但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
  144.         */
  145.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  146.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  147.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  148.     GPIO_Init(GPIOB, &GPIO_InitStructure);


  149.         /* 第4步:配置USART3参数
  150.             - BaudRate = 115200 baud
  151.             - Word Length = 8 Bits
  152.             - One Stop Bit
  153.             - No parity
  154.             - Hardware flow control disabled (RTS and CTS signals)
  155.             - Receive and transmit enabled
  156.         */
  157.         USART_InitStructure.USART_BaudRate = 115200;
  158.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  159.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  160.         USART_InitStructure.USART_Parity = USART_Parity_No;
  161.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  162.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  163.         USART_Init(USART3, &USART_InitStructure);

  164.     /* 若接收数据寄存器满,则产生中断 */
  165.     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

  166.         /* 第5步:使能 USART3, 配置完毕 */
  167.         USART_Cmd(USART3, ENABLE);

  168.     /* 如下语句解决第1个字节无法正确发送出去的问题 */
  169.     USART_ClearFlag(USART3, USART_FLAG_TC);     // 清标志
  170. }

  171. /*************************************************
  172. 函数: void GPIO_Configuration(void)
  173. 功能: GPIO配置
  174. 参数: 无
  175. 返回: 无
  176. **************************************************/
  177. void GPIO_Configuration(void)
  178. {
  179.   GPIO_InitTypeDef GPIO_InitStructure;                                        //定义GPIO初始化结构体

  180.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  181.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  182.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  /* 输出 */
  183.   GPIO_Init(GPIOF, &GPIO_InitStructure);
  184. }

  185. /*************************************************
  186. 函数: void Timer2_Configuration(void)
  187. 功能: TIM2 配置
  188. 参数: 无
  189. 返回: 无
  190. 定时计算:(1 /(72 / (36 - 1 + 1))) * 781 us = 390.5us
  191. **************************************************/
  192. void Timer2_Configuration(void)
  193. {
  194.   TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
  195.    
  196.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);            //打开TIM2定时器的时钟
  197.   
  198.   
  199.   TIM_DeInit(TIM2);                                                    //TIMx寄存器重设为缺省值
  200.   
  201.   TIM_TimeBaseStructure.TIM_Period = 781;                            //自动重装载寄存器周期的值
  202.   TIM_TimeBaseStructure.TIM_Prescaler=36 - 1;               //TIMx 时钟频率除数的预分频值
  203.   TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //采样分频
  204.   TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  205.   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  206.   
  207.   TIM_ARRPreloadConfig(TIM2, ENABLE);                       //允许自动重装载寄存器(ARR)
  208.   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);                        //允许TIM2溢出中断
  209.   
  210.   TIM_Cmd(TIM2, ENABLE);        //开启时钟
  211. }

  212. /*******************************************************************/
  213. /*                                                                 */
  214. /* STM32向串口3发送1字节                                           */
  215. /*                                                                 */
  216. /*                                                                 */
  217. /*******************************************************************/
  218. void Uart3_PutChar(u8 ch)
  219. {
  220.   /* 发送使能 */
  221.   GPIO_SetBits(GPIOF, GPIO_Pin_10);                /* DE = 1 */
  222.   /* 接收禁止 */
  223.   GPIO_SetBits(GPIOF, GPIO_Pin_11);         /* nRE = 1 */

  224.   USART_SendData(USART3, (u8) ch);
  225.   while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);        //注意此句与RS232不同

  226.   //注意:因为RS485的半双工方式,在RS485发送数据完毕后,需要把RS485设置在接收状态,否则收不到主机的数据
  227.   /* 接收使能 */
  228.   GPIO_ResetBits(GPIOF, GPIO_Pin_11);         /* nRE = 0 */
  229.   /* 发送禁止 */
  230.   GPIO_ResetBits(GPIOF, GPIO_Pin_10);        /* DE = 0 */
  231. }

  232. /*******************************************************************/
  233. /*                                                                 */
  234. /* STM32在串口3接收1字节                                           */
  235. /* 说明:串口接收中断                                              */
  236. /*                                                                 */
  237. /*******************************************************************/
  238. void USART3_IRQHandler(void)            //在中断服务程序中,由于主机响应中断时并不知道是哪个中断源发出中断请求,因此必须在中断服务程序中对中断源进行判别,然后分别进行处理。当然,如果只涉及到一个中断请求,是不用做上述判别的。但是无论什么情况,做上述判别是个好习惯
  239. {
  240.   /* 接收使能 */
  241.   GPIO_ResetBits(GPIOF, GPIO_Pin_11);         /* nRE = 0 */
  242.   /* 发送禁止 */
  243.   GPIO_ResetBits(GPIOF, GPIO_Pin_10);        /* DE = 0 */

  244.   if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)    //若接收数据寄存器满
  245.   {     
  246.     comm = USART_ReceiveData(USART3);   //此语句作用:将USART_DR寄存器的内容传到comm里。另外,在单缓冲器模式下,软件读USART_DR寄存器则完成对RXNE位清除。[注意]在多缓冲器模式下,必须通过软件清零"传输完成标志"DMA1_FLAG_TCx(即:令DMA_IFCR的位CTCIFx=1),否则将会无法跳出中断服务程序,出现一次中断请求无数次响应的后果
  247.    
  248.         if(comm == 0x63)                    //上位机自动查找采集器是否在线
  249.         {                         
  250.           comm = 0;      
  251.       Uart3_PutChar(0x63);              //发送CP的ASCII码
  252.       Uart3_PutChar(0x70);                                                        
  253.         }  
  254.   }
  255. }

  256. /*************************************************
  257. 函数: void TIM2_IRQHandler(void)
  258. 功能: TIM2中断处理函数
  259. 参数: 无
  260. 返回: 无
  261. 说明:390.5us中断1次
  262. **************************************************/
  263. void TIM2_IRQHandler(void)
  264. {
  265.    if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  266.    {      
  267.       TIM_ClearITPendingBit(TIM2,TIM_IT_Update);         //清除中断标志
  268.       gototime = 1;
  269.    }
  270. }

  271. /*************************************************
  272. 函数: int main(void)
  273. 功能: main主函数
  274. 参数: 无
  275. 返回: 无
  276. **************************************************/
  277. int main(void)
  278. {
  279.   u16 i;

  280.   RCC_Configuration();
  281.   ADC_Configuration();            //配置PC0 为ADC1_IN10
  282.   GPIO_Configuration();
  283.   NVIC_Configuration();
  284.   USART3_Configuration();
  285.   Timer2_Configuration();


  286.   /* 接收使能 */
  287.   GPIO_ResetBits(GPIOF, GPIO_Pin_11);         /* nRE = 0 */
  288.   /* 发送禁止 */
  289.   GPIO_ResetBits(GPIOF, GPIO_Pin_10);        /* DE = 0 */

  290.   while(1)
  291.   {
  292.     if (comm == 0x7a)                           //单片机发送数据给PC机
  293.         {      
  294.       for(i = 0;i < 256;i++)                    //根据过采样技术,每提高一位AD分辨率,需要增加4倍的采样率;从12位AD分辨率增加到16位AD分辨率,即增加4位,所以需要增加256倍的采样率
  295.       {
  296.         gototime = 0;
  297.         TIM_Cmd(TIM2, ENABLE);                                //开启时钟
  298.             ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //软件启动ADC转换
  299.             while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); //等待转换结束
  300.             ad = 0;
  301.                 ad = ADC_GetConversionValue(ADC1);                        //读取ADC值                     
  302.         tempu32 += ad;                                      //累加        
  303.         while(gototime == 0);                                                //延时:390.5us。采样率:10/秒
  304.         TIM_Cmd(TIM2, DISABLE);                                //关闭时钟
  305.       }

  306.           //以下数据处理和发送会占用一定的时间,如果我们不采用过采样技术,可以把以下代码放在TIM2定时之内处理                            
  307.       ad = tempu32 >> 4;                        //16位分辨率,累加值右移4位
  308.       ah = ad >> 8;                                                    //高8位
  309.       al = ad & 0xff;                                   //低8位
  310.       Uart3_PutChar(ah);
  311.       Uart3_PutChar(al);
  312.                             
  313.       tempu32 = 0;   
  314.     }                                                         
  315.   }
  316. }
复制代码
0.png
所有资料51hei提供下载:
55593383LabVIEW-NTCthermistor-temperature (1).rar (490.51 KB, 下载次数: 13)
回复

使用道具 举报

无效楼层,该帖已经被删除
cr8526 发表于 2019-8-22 23:37 | 显示全部楼层
楼主,,请问做这个项目是不是要编好LAbview程序 外还要 编STM32单片机的程序啊 ?不是编好labview程序 直接输到 STM那 就可以 了吗
回复

使用道具 举报

无效楼层,该帖已经被删除
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|单片机论坛 |51黑电子论坛技术交流 QQ 管理员QQ:125739409;技术交流QQ群636986012

Powered by 单片机教程网

快速回复 返回顶部 返回列表