找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7960|回复: 5
收起左侧

STM32磁悬浮

  [复制链接]
ID:224179 发表于 2017-8-22 21:24 | 显示全部楼层 |阅读模式

上学期做的课程设计的一部分,


  以前做过基于模电的磁悬浮,误差很大,调节不方便,需要多各元件进行,三极管发热的情况也不容乐观。所以在学习stm32的adc功能之后,想使用stm32单片机取代电位比较器。
  stm32的adc功能比较强大,根据读的st官方技术手册,使用多通道后,adc的采样速度甚至能达到us级,能满足很多设计要求很高的场景,足够磁悬浮使用。


1. 了解掌握stm32的综合运用方法
2. 加强了解 l298模块的使用
3. 加强了解霍尔传感器的使用
4. 加强了解 adc的使用


二、主要仪器设备、试剂或材料


1. PC,stm32
2. 霍尔传感器
3. L298n
4. 杜邦线 电线若干
      

001

001




三、实验方法与步骤
代码(部分)
  1. /* Includes------------------------------------------------------------------*/
  2. //# include <stdio. h>
  3. //# include <stdlib. h>
  4. #include "stm32f10x.h"
  5. #include"lcd1602.h"
  6. //#include "misc.h"
  7. //#include "misc.c"
  8. #include<stm32f10x_adc.h>
  9. //#include<stm32f10x_flash.h>
  10. /********************************宏定义------------------------------------*/
  11. #define ADC1_DR_Address    ((u32)0x4001244C)
  12. #define ADC3_DR_Address    ((u32)0x40013C4C)
  13. /********************************变量定义------------------------------------*/
  14. ADC_InitTypeDefADC_InitStructure;
  15. DMA_InitTypeDefDMA_InitStructure;
  16. GPIO_InitTypeDefGPIO_InitStructure; //定义GPIO初始化结构体
  17. vu16 ADC1ConvertedValue = 0,ADC3ConvertedValue = 0;
  18. ErrorStatus HSEStartUpStatus;
  19. int AD_value;
  20. float CountV;
  21. float Std = (3.3)/4096;
  22. int CountV1;
  23. int CountV2;
  24. int CountV3;
  25. int hall;
  26. unsigned int jj = 0;
  27. //此表为 LED 的字模, 共阴数码管 0-9  -
  28. unsigned int Disp_Tab[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};  //段码控制
  29. //此表为8个数码管位选控制, 共阴数码管 1-8个 -
  30. unsigned intdispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F};    //位选控制   查表的方法控制
  31. unsigned int LedOut[10];        //变量定义
  32.    
  33. /*********************************声明函数 -----------------------------------------------*/
  34. void RCC_Configuration(void);
  35. voidGPIO_Configuration(void);
  36. voidNVIC_Configuration(void);
  37. void delay_nms(u16 time);
  38. void Delay(vu32 nCount);
  39. /*******************************************************************************
  40. *
  41. *            主函数
  42. *
  43. *******************************************************************************/
  44. int main(void)
  45. { unsigned int  LedNumVal = 0 ,LedNumVal1 = 0;     //变量定义
  46. #ifdef DEBUG
  47.   debug();
  48. #endif
  49.                                                                                                                  
  50.   //RCC配置
  51.   RCC_Configuration();
  52.   // NVIC配置
  53.   NVIC_Configuration();
  54.   //GPIO配置
  55.   GPIO_Configuration();
  56.   //DMA1 通道配置
  57.   DMA_DeInit(DMA1_Channel1); //设置成CH1 DMA中包含了7个通道(CH1-CH7)
  58.   DMA_InitStructure.DMA_PeripheralBaseAddr =ADC1_DR_Address; //给DMA起始地址
  59.   DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&ADC1ConvertedValue;//DMA连接在内存中的变量地址
  60.   DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralSRC; //设置DMA传输方向单向传输
  61.   DMA_InitStructure.DMA_BufferSize = 1; //设置DMA在传输时缓冲区的长度
  62.   DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; //设置DMA的外设递增模式
  63.   DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Disable;//设置DMA的内存递增模式
  64.   DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;//DMA在访问时每次操作的数据长度
  65.   DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord;
  66.   DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;//DMA的传输模式,连续不断的循环模式
  67.   DMA_InitStructure.DMA_Priority =DMA_Priority_High; //DMA的优先级别:可以分为4级
  68.   DMA_InitStructure.DMA_M2M =DMA_M2M_Disable;//DMA的2个memory中的变量互相访问的
  69.   DMA_Init(DMA1_Channel1, &DMA_InitStructure);//DMA整个模块初始化
  70.   //开启DMA通道1
  71.   DMA_Cmd(DMA1_Channel1, ENABLE);
  72.      
  73.   // ADC1 配置
  74.   ADC_InitStructure.ADC_Mode =ADC_Mode_FastInterl; //ADC1工作在独立模式
  75.   ADC_InitStructure.ADC_ScanConvMode =ENABLE;//使能扫描
  76.   ADC_InitStructure.ADC_ContinuousConvMode =ENABLE;;//ADC转换工作在连续模式
  77.   ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None;//由软件控制转换
  78.   ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right;//转换数据右对齐
  79.   ADC_InitStructure.ADC_NbrOfChannel = 14;//转换通道为通道1
  80.   ADC_Init(ADC1, &ADC_InitStructure); //初始化ADC
  81.   //ADC1选择信道14,音序器等级1,采样时间239.5个周期
  82.   ADC_RegularChannelConfig(ADC1,ADC_Channel_14, 1, ADC_SampleTime_28Cycles5);   
  83.   //使能ADC1模块DMA
  84.   ADC_DMACmd(ADC1, ENABLE);
  85.     //打开ADC1
  86.   ADC_Cmd(ADC1, ENABLE);
  87. //重置ADC1校准寄存器
  88.   ADC_ResetCalibration(ADC1);
  89. //等待ADC1校准重置完成
  90. while(ADC_GetResetCalibrationStatus(ADC1));  
  91.   //开始ADC1校准
  92.   ADC_StartCalibration(ADC1);
  93. //等待ADC1校准完成
  94.   while(ADC_GetCalibrationStatus(ADC1));
  95. //使能ADC1软件开始转换
  96.   ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  97. //*****************************************************************************//
  98.     L1602_init();
  99.         L1602_Clear();
  100.        GPIO_SetBits(GPIOC,GPIO_Pin_2);
  101.             L1602_string(1,1,"    wj works   ");
  102.            L1602_string(2,1,"   ALL SET OK  ");
  103.            delay_nms(1000);
  104.   while (1)
  105.   {  unsignedint i ;
  106.       
  107. // L1602_Clear();
  108.            int num = 100;
  109.     int str[4];
  110.     //itoa(num, str, 10);
  111.             AD_value =ADC_GetConversionValue(ADC1);
  112.          CountV   = ADC_GetConversionValue(ADC1)*    Std;
  113.             CountV1  = CountV/1;
  114.       str[0] = CountV1 ;
  115.            
  116. //                      "WJWORKSVoltage "
  117. //L1602_string(1,1,"WJWORKS");
  118. //L1602_string(2,1,"Voltage is  ");
  119. //L1602_DispFloatNum(2,12,CountV);
  120.            // L1602_string(2,16,"V");
  121.            if(CountV>=1.1) GPIO_SetBits(GPIOE,GPIO_Pin_5);
  122.         elseGPIO_ResetBits(GPIOE,GPIO_Pin_5);
  123. //delay_nms(200);
  124.    }
  125. }
  126. void Delay(vu32 nCount)
  127. {
  128.   for(; nCount != 0; nCount--);
  129. }
  130. /*******************************************************************************
  131. *
  132. *            RCC配置
  133. *
  134. *******************************************************************************/
  135. void RCC_Configuration(void)
  136.                      
  137.       
  138. {
  139. //复位RCC外部设备寄存器到默认值
  140.   RCC_DeInit();
  141.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOB的时钟
  142.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIOB的时钟
  143.             RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB的时钟
  144.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能GPIOA的时钟
  145.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);//使能GPIOD的时钟
  146.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//打开USART的定时器
  147.                  
  148.                  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  149.   //打开外部高速晶振
  150.   RCC_HSEConfig(RCC_HSE_ON);
  151. //等待外部高速时钟准备好
  152.   HSEStartUpStatus = RCC_WaitForHSEStartUp();
  153.   //外部高速时钟已经准别好
  154.   if(HSEStartUpStatus == SUCCESS)  
  155.   {
  156.    
  157.    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  158.    
  159.     FLASH_SetLatency(FLASH_Latency_2);
  160.   
  161.    //配置AHB(HCLK)时钟=SYSCLK
  162.     RCC_HCLKConfig(RCC_SYSCLK_Div1);
  163.   
  164.     //配置APB2(PCLK2)钟=AHB时钟
  165.     RCC_PCLK2Config(RCC_HCLK_Div1);
  166.     //配置APB1(PCLK1)钟=AHB 1/2时钟
  167.     RCC_PCLK1Config(RCC_HCLK_Div2);  
  168.     //配置ADC时钟=PCLK2 1/4
  169.     RCC_ADCCLKConfig(RCC_PCLK2_Div4);
  170.   
  171.     //配置PLL时钟 == 外部高速晶体时钟*9
  172.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
  173.    
  174.       //配置ADC时钟= PCLK2/4
  175.     RCC_ADCCLKConfig(RCC_PCLK2_Div4);
  176.    //使能PLL时钟
  177.     RCC_PLLCmd(ENABLE);  
  178.    //等待PLL时钟就绪
  179.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) ==RESET)  
  180.     {
  181.     }
  182.     //配置系统时钟 = PLL时钟
  183.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  184.    //检查PLL时钟是否作为系统时钟
  185.     while(RCC_GetSYSCLKSource() != 0x08)  
  186.     {
  187.     }
  188.   }
  189.   // 开启DMA1时钟 Enable
  190.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 ,ENABLE);
  191.   //开启ADC1时钟
  192.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1   , ENABLE);
  193.                   
  194.     //下面是给各模块开启时钟
  195.     //启动GPIO
  196.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB ,ENABLE);
  197.     //启动AFIO
  198.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  199.     //启动DMA时钟
  200.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  201.     //启动ADC1时钟
  202.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  203. }
  204. /*************************************************
  205. 函数: voidGPIO_Config(void)
  206. 功能: GPIO配置
  207. **************************************************/
  208. void GPIO_Configuration(void)
  209. {
  210.    
  211.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//| RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO
  212.     GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
  213.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
  214.     GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
  215.     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; //引脚频率50M
  216.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  217.       
  218.        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  219.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  220.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
  221.            GPIO_Init(GPIOC,&GPIO_InitStructure);
  222.       
  223.       
  224.     //配置PA0为模拟输入
  225.       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  226.       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  227.       GPIO_Init(GPIOA, &GPIO_InitStructure);
  228.       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  229.       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  230.       GPIO_Init(GPIOA, &GPIO_InitStructure);
  231.    
  232.            
  233.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//*************指示灯配置
  234.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  235.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
  236.            GPIO_Init(GPIOE,&GPIO_InitStructure);
  237.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  238.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  239.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
  240.            GPIO_Init(GPIOE,&GPIO_InitStructure);
  241.            
  242.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  243.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  244.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_7|GPIO_Pin_13|GPIO_Pin_14;
  245.            GPIO_Init(GPIOD,&GPIO_InitStructure);
  246.            
  247.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  248.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  249.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
  250.            GPIO_Init(GPIOB,&GPIO_InitStructure);
  251.                  
  252.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  253.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  254.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
  255.            GPIO_Init(GPIOA,&GPIO_InitStructure);
  256.            
  257.                  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  258.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  259.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13;
  260.            GPIO_Init(GPIOE,&GPIO_InitStructure);
  261.            
  262.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置
  263.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  264.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
  265.            GPIO_Init(GPIOC,&GPIO_InitStructure);
  266.            
  267.            GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//-------------------------------------输出配置d10
  268.            GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  269.            GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
  270.            GPIO_Init(GPIOD,&GPIO_InitStructure);
  271. }
  272. void delay_nms(u16 time)
  273.            {  
  274.                  u16 i=0;  
  275.                  while(time--)
  276.                       {
  277.                             i=12000;
  278.                             while(i--) ;}}
  279.                            
  280. /*******************************************************************************
  281. * Function Name  : NVIC_Configuration
  282. * Description    : Configures Vector Table base location.
  283. * Input          : None
  284. * Output         : None
  285. * Return         : None
  286. *******************************************************************************/
  287. void NVIC_Configuration(void)
  288. {
  289.   NVIC_InitTypeDef NVIC_InitStructure;
  290. #ifdef  VECT_TAB_RAM
  291.   /* Set the Vector Table base location at0x20000000 */
  292.   NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  293. #else  /* VECT_TAB_FLASH  */
  294.   /* Set the Vector Table base location at0x08000000 */
  295.   NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);   
  296. #endif
  297.   /* Configure and enable ADC interrupt */
  298.   NVIC_InitStructure.NVIC_IRQChannel =ADC1_2_IRQn;
  299. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  300.   NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;
  301.   NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
  302.   NVIC_Init(&NVIC_InitStructure);
  303. }
  304. #ifdef  DEBUG
  305. /*******************************************************************************
  306. * Function Name  : assert_failed
  307. * Description    : Reports the name of the source file andthe source line number
  308. *                  where the assert_param errorhas occurred.
  309. * Input          : - file: pointer to the source filename
  310. *                  - line: assert_param errorline source number
  311. * Output         : None
  312. * Return         : None
  313. *******************************************************************************/
  314. void assert_failed(u8* file,u32 line)
  315. {
  316.   /* User can add his own implementation toreport the file name and line number,
  317.      ex: printf("Wrong parameters value:file %s on line %d\r\n", file, line) */
  318.   /* Infinite loop */
  319.   while (1)
  320.   {
  321.   }
  322. }
  323. #endif
复制代码

四、实验总结
  弥补了之前使用电位比较器的缺点,因为点位比较器没有反馈的机制,所以最后小球在空中震荡的频率会越来越快,最后超过阈值会吸在通电线圈上。
现在通过stm32可以通过程序,例如
增加一个刹车的机制,设置一个随时间变化的比例,通过改变in1,in2,ena的电平状态,逐步增加刹车时间,完成稳定悬浮体的作用。

评分

参与人数 1黑币 +11 收起 理由
564654654 + 11 赞一个!

查看全部评分

回复

使用道具 举报

ID:230171 发表于 2017-8-31 09:22 | 显示全部楼层
我实验用电源直接给电磁铁通电 磁铁会在线圈中间悬浮,在外面根本悬停不了 请问是不是在线圈上面加块铁片?
回复

使用道具 举报

ID:68875 发表于 2017-9-3 22:12 | 显示全部楼层
不错的东西,收藏了
回复

使用道具 举报

ID:377919 发表于 2019-5-19 13:04 | 显示全部楼层
最近正要动手,谢谢分享
回复

使用道具 举报

ID:1092471 发表于 2023-9-2 15:04 | 显示全部楼层
可以发下源代码吗?
回复

使用道具 举报

ID:149043 发表于 2024-9-22 11:09 来自手机 | 显示全部楼层
大佬,有完整的代码吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

Powered by 单片机教程网

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