找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1084|回复: 0
收起左侧

STM32单片机ADC采样+TM1637显示程序

[复制链接]
ID:540173 发表于 2022-5-20 16:24 | 显示全部楼层 |阅读模式
本程序能使用STM32进行阈值检测,并ADC采样显示,结果显示在TM1637上。

单片机源程序如下:
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "lcd.h"
  6. #include "adc.h"
  7. #include "TM1637.h"
  8. #include "timer.h"

  9. //ALIENTEK Mini STM32开发板范例代码15
  10. //ADC实验  
  11. #define   Code_Freq 20   //编码输出频率
  12. u8 delay_time = 1000/Code_Freq;  //编码延时时间          

  13. u8 DATA[4]={0};
  14. u8 wrong=0;  //记录错误
  15. extern u8 DATA_Code[24];
  16. extern u8 count;
  17. extern u8 ADC_TIMES;
  18. int main(void)
  19. {

  20.         int i=0;
  21.         NVIC_InitTypeDef NVIC_InitStructure;
  22.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
  23.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
  24.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  25.          TM1637_Init();//。。。。。。。。。。。。。。。数码管初始化
  26.          LED0=!TM1637_VCC;//  led提示显示数码管
  27.         delay_init();                     //延时函数初始化          
  28.         uart_init(9600);                 //串口初始化为9600
  29.         LED_Init();                                  //初始化与LED连接的硬件接口
  30.         LCD_Init();
  31.         Adc_Init();                                  //ADC初始化            
  32.         POINT_COLOR=BLUE;//设置字体为蓝色
  33.         LCD_ShowString(60,130,200,16,16,"ADC_CH1_VAL:");
  34.         TM1637_NixieTubeDisplay();
  35.         TM1637_NixieTubeDisplayChar(1,0);//第一位显示1
  36.         TM1637_NixieTubeDisplayChar(2,1);//第二位显示2
  37.         TM1637_NixieTubeDisplayChar(3,2);//第三位显示3
  38.         TM1637_NixieTubeDisplayChar(4,3);//第四位显示4         
  39.         GET_Range();//获取最新范围
  40.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  41.         TIM3_Int_Init(delay_time*5,7199);          //采样频率设置为Code_Freq两倍
  42.         TM1637_VCC=0;
  43.         LED0=!TM1637_VCC;
  44.         LCD_ShowString(60,100,200,16,16,"Receiving");
  45.         while(1)
  46.         {   
  47.     if(DATA_Code[0]+DATA_Code[1]+DATA_Code[2]+DATA_Code[3]==0&&DATA_Code[4]+DATA_Code[5]+DATA_Code[6]+DATA_Code[7]==4)//判断依据  用ADC_TIMES在第一次时候有问题
  48.                         {
  49.                                 NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; //IRQ通道关闭
  50.                                 NVIC_Init(&NVIC_InitStructure);  //不过可能之后不通过卡进死循环
  51.                                 for(i=0;i<4;i++)
  52.                                 {
  53.                                  DATA[i]=DATA_Code[8+i*4]*8+DATA_Code[9+i*4]*4+DATA_Code[10+i*4]*2+DATA_Code[11+i*4];  //计算输出显示编码
  54.          if(DATA[i]>9||(ADC_TIMES>8&&ADC_TIMES<23))  //大于9则错误  adc_times 不能解决随时关闭造成的错误  要改关闭算法或者记录长时间显示的数值保持
  55.                                         { wrong++;
  56.                                         }       
  57.                                  DATA[i]=DATA[i]%10;                 
  58.                                  LCD_ShowxNum(16*(i+1),200,DATA[i],1,16,0);//实时显示测得编码
  59.                                 }
  60.                                 if(wrong==0)//没有码位错误才显示
  61.                                 {
  62.                                         TM1637_VCC=1;
  63.                                         LED0=!TM1637_VCC;
  64.                                         delay_ms(1);
  65.                                         TM1637_NixieTubeDisplay();
  66.                                         TM1637_NixieTubeDisplayChar(DATA[0],0);//用i循环只显示最后一位
  67.                                         TM1637_NixieTubeDisplayChar(DATA[1],1);
  68.                                         TM1637_NixieTubeDisplayChar(DATA[2],2);
  69.                                         TM1637_NixieTubeDisplayChar(DATA[3],3);
  70.                                         LCD_Fill(50,100,150,120,WHITE);
  71.                                         LCD_ShowString(60,100,200,16,16,"Received");
  72.                                         delay_ms(1000);
  73.                                 }
  74.                                 ADC_TIMES=0;
  75.                                 count=0;  //和中断内数字有关系所以要先配置
  76.                                 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道开启
  77.                                 NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  78.                                 wrong=0;
  79.                         }                 
  80.                 if(count>10&&TM1637_VCC==1)//不能在已经灭的时候进入 否则不灵
  81.                 {
  82.                         delay_ms(1000);//合计延迟5秒左右  但是不能大于1000
  83.                         delay_ms(1000);
  84.                         delay_ms(1000);
  85.                         //delay_ms(100);
  86.                         LCD_ShowString(60,100,200,16,16,"had stopped");
  87.                         TM1637_VCC=0;
  88.                         LED0=!TM1637_VCC;
  89.                         count=0;
  90.                 }
  91.         }                                                                                            
  92. }       
复制代码
  1. #include "adc.h"
  2. #include "delay.h"
  3. #include "lcd.h"
  4. #include "math.h"

  5. u16 VAL_MAX=0;
  6. u16 VAL_MIN=0;
  7. u16 VAL_JUDGE=1300;
  8. u16 count=0;
  9. void  GET_Range(void)
  10. { int i=0;
  11.         int j=0;
  12.         int t=0;
  13.         u16 adcx;
  14.         u16 MAX[10]={100,100,100,100,100,100,100,100,100,100};//第一个最小
  15.         u16 MIN[10]={5000,5000,5000,5000,5000,5000,5000,5000,5000,5000};//第一个最大
  16.         for(i=0;i<100;i++)
  17.         {  
  18.                 adcx=Get_Adc_Average(ADC_Channel_1,10);
  19.                 if(adcx>=(MAX[7]+MAX[8]+MAX[9])/3-50)
  20.                 {
  21.                         MAX[0]=adcx;
  22.                         for(j=0;j<9;j++)
  23.                         {
  24.                                 if(MAX[j]>MAX[j+1]) //前面的要小
  25.                                         {t=MAX[j];
  26.                                          MAX[j]=MAX[j+1];
  27.                                          MAX[j+1]=t;
  28.                                         }
  29.                         }
  30.                                   //
  31.                 }
  32.                 if(adcx<=(MIN[7]+MIN[8]+MIN[9])/3+50)
  33.                 { MIN[0]=adcx;
  34.                         for(j=0;j<9;j++)
  35.                         {
  36.                                 if(MIN[j]<MIN[j+1]) //前面的要大
  37.                                         {
  38.                                                 t=MIN[j];
  39.                                                 MIN[j]=MIN[j+1];
  40.                                                 MIN[j+1]=t;
  41.                                         }
  42.                         }
  43.                        
  44.                 }
  45.         }
  46.         VAL_MAX=(MAX[3]+MAX[4]+MAX[5]+MAX[6]+MAX[7])/5;
  47.         VAL_MIN=(MIN[3]+MIN[4]+MIN[5]+MIN[6]+MIN[7])/5;
  48.         //VAL_JUDGE=(VAL_MAX+VAL_MIN)/2;
  49.         VAL_JUDGE=((VAL_MAX+VAL_MIN)/2-VAL_MIN)*0.9+VAL_MIN;//略微偏下
  50.         if(VAL_MAX-VAL_MIN<400)//200MV左右 防止检测的都是一
  51.         { VAL_MIN=VAL_MIN-500;//有待商榷数值
  52.                 VAL_JUDGE=(VAL_MAX+VAL_MIN)/2;
  53.         }
  54.        
  55. }
  56. u8 GET_CODE(void)  //采集   现在只判断一和零 没有中间 正弦波时候清空  一定要特殊标记 延迟五秒关闭
  57. {         u16 adcx;
  58.           adcx=Get_Adc_Average(ADC_Channel_1,10);
  59.                 LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
  60.         if(adcx>VAL_JUDGE)  //阈值需要修改
  61.         {        count++;
  62.                 return 1;       
  63.         }
  64.         else
  65.         {       
  66.                 count=0;
  67.                 return 0;
  68.         }               
  69. }  
  70.                   
  71. //初始化ADC
  72. //这里我们仅以规则通道为例
  73. //我们默认将开启通道0~3                                                                                                                                          
  74. void  Adc_Init(void)
  75. {        
  76.         ADC_InitTypeDef ADC_InitStructure;
  77.         GPIO_InitTypeDef GPIO_InitStructure;

  78.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟


  79.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

  80.         //PA1 作为模拟通道输入引脚                        
  81.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  82.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
  83.         GPIO_Init(GPIOA, &GPIO_InitStructure);       

  84.         ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

  85.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
  86.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
  87.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
  88.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
  89.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
  90.         ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
  91.         ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  92.   
  93.         ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
  94.        
  95.         ADC_ResetCalibration(ADC1);        //使能复位校准  
  96.          
  97.         while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
  98.        
  99.         ADC_StartCalibration(ADC1);         //开启AD校准

  100.         while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束

  101. //        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能

  102. }                                  
  103. //获得ADC值
  104. //ch:通道值 0~3
  105. u16 Get_Adc(u8 ch)   
  106. {
  107.           //设置指定ADC的规则组通道,一个序列,采样时间
  108.         ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      
  109.   
  110.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能       
  111.          
  112.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

  113.         return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
  114. }

  115. u16 Get_Adc_Average(u8 ch,u8 times)
  116. {
  117.         u32 temp_val=0;
  118.         u8 t;
  119.         for(t=0;t<times;t++)
  120.         {
  121.                 temp_val+=Get_Adc(ch);
  122.         }
  123.         return temp_val/times;
  124. }          
复制代码

Keil代码下载:
代码.7z (233.59 KB, 下载次数: 54)

评分

参与人数 1黑币 +10 收起 理由
admin + 10 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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