蓝桥杯单片机读取外部电压

请问我想用蓝桥杯的单片机读取外部输入的电压,应该怎么做呢(不是读取光敏和电位器的电压,就是AIN0输入的外部电压),比如我有一个电池,该怎么通过AIN0读取其电压,请给出电路接法和代码

引用chatGPT作答,要使用蓝桥杯单片机读取外部输入的电压,需要将外部电压接到单片机的模拟输入端口,通常是AIN0。下面是一个简单的电路接法和代码示例。

电路接法:
将待测电压接到单片机的AIN0输入引脚上,同时要将其它引脚分别接好。

代码示例:
这是一个使用C语言编写的简单程序,它会读取AIN0输入端口上的电压,并将其显示在LCD屏幕上。请注意,此代码示例仅供参考,具体实现可能需要进行适当的修改以适应您的具体情况。

#include <reg52.h>
#include <intrins.h>

sbit LCD_RS = P2^6;     //LCD1602控制端口定义
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^7;
sbit LCD_D4 = P0^0;
sbit LCD_D5 = P0^1;
sbit LCD_D6 = P0^2;
sbit LCD_D7 = P0^3;

void Delay1ms()     //延时函数
{
    unsigned char a,b;
    for(b=2;b>0;b--)
        for(a=246;a>0;a--);
}

void LCD_Write_Cmd(unsigned char cmd)     //写指令
{
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 1;
    LCD_D7 = cmd & 0x80;
    LCD_D6 = cmd & 0x40;
    LCD_D5 = cmd & 0x20;
    LCD_D4 = cmd & 0x10;
    Delay1ms();
    LCD_EN = 0;
    Delay1ms();
    LCD_EN = 1;
    LCD_D7 = cmd & 0x08;
    LCD_D6 = cmd & 0x04;
    LCD_D5 = cmd & 0x02;
    LCD_D4 = cmd & 0x01;
    Delay1ms();
    LCD_EN = 0;
    Delay1ms();
}

void LCD_Write_Data(unsigned char dat)     //写数据
{
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 1;
    LCD_D7 = dat & 0x80;
    LCD_D6 = dat & 0x40;
    LCD_D5 = dat & 0x20;
    LCD_D4 = dat & 0x10;
    Delay1ms();
    LCD_EN = 0;
    Delay1ms();
    LCD_EN = 1;
    LCD_D7 = dat & 0x08;
    LCD_D6 = dat & 0x04;
    LCD_D5 = dat & 0x02;
    LCD_D4 = dat & 0x01;
    Delay1ms();
    LCD_EN = 0;
    Delay1ms();
}

void LCD_Init()     //LCD1602初始化
{
    LCD_Write_Cmd(0x38);
    LCD_Write_Cmd(0x08);
    LCD_Write_Cmd(0x01);
    LCD_Write_Cmd(0x06);
    LCD_Write_Cmd(0x0c);
}

void main()
{
    unsigned char a, b;
    unsigned int vol;
    char str[17];

    TMOD = 0x01;
    TH0 = 0;      //计时器0初始化
    TL0 = 0;
    TR0 = 1;
    LCD_Init();    //LCD1602初始化

    while(1)
    {
        ADC_CONTR = 0x80;    //启动ADC转换
        while(!ADC_CONTR & 0x20);    //等待转换完成
        ADC_CONTR &= ~0x20;    //清除ADC转换完成标志位
        vol = ADC_RES;    //读取转换结果

        vol = vol * 0.00488;   //计算电压值

        sprintf(str, "Voltage: %dmV", vol);    //格式化输出
        for(a = 0; a < 16; a++)
        {
            LCD_Write_Cmd(0x80 + a);   //在第一行显示
            LCD_Write_Data(str[a]);
        }

        for(b = 0; b < 16; b++)
        {
            LCD_Write_Cmd(0xc0 + b);    //在第二行显示
            LCD_Write_Data(str[a + b]);
        }
    }
}

该程序中使用了定时器0来进行ADC转换的间隔控制,ADC_RES用于存储ADC转换结果。ADC转换后通过计算转换值来得出对应电压值,并使用sprintf函数进行格式化输出,最终将结果显示在LCD上。请注意,程序中的计算电压值的代码需要根据具体硬件电路进行修改。

以下回答结合了ChatGPT:
要使用单片机读取外部输入的电压,需要将电压信号转换为单片机可以读取的数字信号。一种常见的转换方式是使用模数转换器(ADC)。

对于单片机上的AIN0输入引脚,一般可以通过连接一个电阻分压电路来将电压转换为单片机可以读取的范围内的电压信号。以下是一个简单的电路接法:


             +5V
              |
              R1
              |
Vin ---------+------ AIN0
              |
              R2
              |
             GND

其中,Vin为外部输入的电压,R1和R2为两个电阻,其比值决定了转换的放大倍数。为了防止电压过高或过低,电阻的取值应该合理选择。

下面是一个简单的基于STC89C52单片机的示例代码,使用ADC模块读取AIN0引脚上的电压并将其显示在LCD上:

#include <reg52.h>
#include <intrins.h>

#define LCD_DATA P0
sbit RS = P2^6;
sbit RW = P2^5;
sbit E = P2^7;

void delay(unsigned int n)
{
    while (n--) {
        _nop_();
        _nop_();
    }
}

void lcd_write_cmd(unsigned char cmd)
{
    LCD_DATA = cmd;
    RS = 0;
    RW = 0;
    E = 1;
    delay(1);
    E = 0;
    delay(10);
}

void lcd_write_data(unsigned char dat)
{
    LCD_DATA = dat;
    RS = 1;
    RW = 0;
    E = 1;
    delay(1);
    E = 0;
    delay(10);
}

void lcd_init()
{
    lcd_write_cmd(0x38);
    lcd_write_cmd(0x0c);
    lcd_write_cmd(0x06);
    lcd_write_cmd(0x01);
}

void adc_init()
{
    P1ASF |= 0x01;  // 将P1.0设置为ADC输入
    ADC_RES = 0;    // 清空ADC结果
    ADC_CONTR = 0x88;   // ADC转换器使能、Fadc/2
}

unsigned int adc_read()
{
    unsigned int value;

    ADC_CONTR |= 0x08;  // 启动ADC转换
    while (!(ADC_CONTR & 0x10)); // 等待转换完成
    value = ADC_RES;
    value |= ADC_RESL << 8;
    return value;
}

void main()
{
    unsigned int adc_value;
    unsigned char str[16];

    lcd_init();
    adc_init();

    while (1) {
        adc_value = adc_read();
        sprintf(str, "ADC=%04u", adc_value);
        lcd_write_cmd(0x80);
        for (int i = 0; i < 16; i++) {
            if (str[i] == 0) break;
            lcd_write_data(str[i]);
        }
        delay(100);
    }
}

该示例代码使用P1.0引脚作为ADC输入,并将读取到的ADC值显示在LCD上。

chatgpt:
要通过蓝桥杯单片机读取外部输入的电压,需要进行模拟信号采集和转换,具体的电路接法和代码如下:

电路接法:
将电池的正极连接到单片机板的AIN0输入口,负极接地。

代码:

#include <reg52.h> // 8051系列单片机头文件
#define uint unsigned int // 定义uint为unsigned int类型
#define uchar unsigned char // 定义uchar为unsigned char类型

sbit LED = P2^0; // 定义LED连接的IO口
sbit IN = P1^0; // 定义AIN0连接的IO口

void init() // 初始化函数
{
    P1ASF = 0x01; // P1.0口配置为模拟输入口
    ADC_RES = 0; // 清除ADC转换结果
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_PORT0; // ADC初始化
}

uint getADCResult(uchar ch) // 获取ADC转换结果函数
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch; // 选择通道并启动转换
    _nop_(); // 等待转换结束
    _nop_();
    _nop_();
    _nop_();
    return ADC_RES; // 返回转换结果
}

void main()
{
    uint value; // 定义变量value存放转换结果
    init(); // 初始化
    while(1)
    {
        value = getADCResult(ADC_Channel_0); // 读取AIN0的电压值
        if(value > 500) // 判断电压值是否大于500
            LED = 0; // 如果大于500,则点亮LED
        else
            LED = 1; // 如果小于等于500,则熄灭LED
    }
}


以下内容部分参考ChatGPT模型:


可以使用单片机的ADC模块来读取外部输入的电压,具体的电路接法如下:

将外部电压通过一个电阻分压电路降低电压,然后将分压后的电压接到单片机的AIN0引脚上。电阻分压电路的原理是将输入电压与两个电阻构成一个电压分压器,输出的电压是输入电压与两个电阻的比例关系。

下面是代码示例,假设单片机型号是STC89C52,ADC模块的输入通道为AIN0:

#include <reg52.h>
#include <stdio.h>

sbit ADC_CS = P3^4;  // 定义ADC模块的片选信号
sbit ADC_CLK = P3^5; // 定义ADC模块的时钟信号
sbit ADC_DIN = P3^6; // 定义ADC模块的数据输入信号
sbit ADC_DOUT = P3^7;// 定义ADC模块的数据输出信号

unsigned int GetADCResult(void)
{
    unsigned char i;
    unsigned int value = 0;
    
    ADC_CS = 0;  // 片选信号低电平
    ADC_CLK = 0; // 时钟信号低电平
    ADC_DIN = 1; // 数据输入信号高电平
    
    for(i=0;i<12;i++)
    {
        ADC_CLK = 1; // 时钟信号高电平
        ADC_CLK = 0; // 时钟信号低电平
        value <<= 1; // 数据左移1位
        if(ADC_DOUT) // 如果数据输出信号高电平
        {
            value |= 0x01; // 将数据的最低位设为1
        }
    }
    
    ADC_CS = 1; // 片选信号高电平
    return value; // 返回ADC采集结果
}

void main()
{
    unsigned int adc_value;
    float voltage;
    
    while(1)
    {
        adc_value = GetADCResult(); // 读取ADC采集结果
        voltage = adc_value * 5.0 / 4096.0; // 转换为电压值(假设电源电压为5V)
        printf("Voltage: %.2fV\n", voltage); // 输出电压值
    }
}

以上代码的作用是读取ADC模块的采集结果,并将采集结果转换为电压值输出。在代码中,需要根据实际情况修改ADC模块的引脚定义和电源电压。另外,需要注意电阻分压电路的电阻值选择,以保证输出电压范围在ADC模块输入电压范围内。


如果我的建议对您有帮助、请点击采纳、祝您生活愉快

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
读取外部电压可以使用单片机的模拟输入功能和内部ADC(模数转换器)模块,具体的流程和代码如下:

电路接法:

将需要读取的电压接到单片机的AIN0引脚上,同时将电压地接单片机的GND引脚上。注意电压范围不能大于单片机的工作电压范围。

代码实现:

首先需要初始化ADC模块,指定ADC的输入引脚和参考电压,这里假设参考电压为3V,代码如下:

#include <STC12C5A.H>
#include <intrins.h>

void ADC_Init() {
    //设置ADC时钟为系统时钟的1/32
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_RES;
    //将AIN0设置成ADC输入引脚
    P1ASF |= 0x01;        
    //设置参考电压为3V
    AUXR |= 0x01;         
    ADC_RES = ADC_RES & 0xEF;
}

初始化完成后,我们可以使用以下代码读取AIN0的电压值:

unsigned int ADC_Read() {
    unsigned int val;
    ADC_CONTR = ADC_CONTR | ADC_START | ADC_CHS;      //启动ADC转换
    _nop_();                                          //延时等待转换完成
    _nop_();                                          
    _nop_();                                          //总共延时大约12us
    val = ADC_RES;                                     //获取ADC转换结果
    val |= (unsigned int)ADC_RESL << 8;
    return val;
}

嵌入式系统需要在某个时刻不断地读取AIN0的电压值,可以通过定时器中断或者其他方式实现。假设定时器中断周期为1s,我们可以在中断服务函数中将电压值打印出来:

void Timer0() interrupt 1 { 
    unsigned int val = ADC_Read();            //读取AIN0的电压值
    float v = val * 3.0 / 1024.0;             //计算实际电压值
    printf("%f\r\n", v);                      //打印电压值
}

void main() {
    ADC_Init();                                //初始化ADC模块
    TMOD |= 0x01;                              //设置定时器0为模式1
    TH0 = 0xFC;                                //定时器初值为0xFC67,得出1ms中断
    TL0 = 0x67;                                        
    ET0 = 1;                                    //允许定时器0中断
    EA = 1;                                     //开启总中断
    TR0 = 1;                                    //启动定时器0
    while(1);                                   //程序主循环
}

这样就可以通过AIN0引脚读取外部电压值并打印出来了。
如果我的回答解决了您的问题,请采纳!

首先是题主说的,利用蓝桥杯的板子的ADC引脚测量外部电压,蓝桥杯一般是使用PB0引脚,这里附上ADC相关程序
1)ADC初始化程序

void ADC1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef  ADC_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
  /* ADC1 Configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  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);
  while(ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));
}

2)读取电压值

// 软件触发AD转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
计算电压值
vol=ADC_GetConversionValue(ADC1)*3.3/0xFFF;

另外题主想要的测量电池电压时的接法也比较简单,只需要电池负极接地,正极接到ADC引脚,这里也就是PB0即可测出电池电压。

有用望采纳。

可以借鉴下

#include <stc15f2k60s2.h>
#include <intrins.h>
#include "ds1302.h"
#include "iic.h"
 
typedef unsigned char uchar;
typedef unsigned int uint;
 
code uchar TAB[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf};//显示1-9 灭 -
uchar tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8;
 
uchar key, sec, min, hour, AD, dat;//常用的参数,秒,分,时,数据存放,AD读取
 
uint fre_time, frequ, H_tem, L_tem, H, L;//定义频率采集所需的变量
bit fre_state;
 
uint dat_t;
bit time_state, AD_state;//读取时间标志位,读取电压标志位
 
uchar function;
uchar T_set, V_set;//记录时间显示状态,电压显示状态
bit F_T;//记录频率周期显示状态
 
uchar hour_tem, min_tem, sec_tem;//时间调节临时存放
uchar V_h  = 20, V_l = 10;//电压上限=2.0V  电压下限=1.0V
 
bit inqu_state, thing_num;//记录查询显示状态,存放事件类型
uchar hour_in = 13, min_in = 50, sec_in = 12;//存放发生时间
bit times;//触发标志位
void delay(uint z)//延时函数
{
    uint x, y;
    for(x=z; x>0; x--)
        for(y=845; y>0; y--);
}
 
void timer_int()//定时器初始,一般是手写放在这里面
{
    EA = 1;
    TR0 = 1;//定时器016位,定时1ms,定时中断
    ET0 = 1;
    TMOD |= 0X01;
    TH0 = (65535-1000)/256;
    TL0 = (65535-1000)%256;
 
    TMOD |= 0X20;// 定时器18位自动装载,用来定时采样频率,5us
    TH1 = 255-5;
    TL1 = 255-5;
}
 
void display()//显示函数,配合定时器0中断使用,达到循环扫描
{
    static uchar i;//定义静态变量i
    switch(i)
    {
        case 0: P2=0XC0; P0=0X01; P2=0XE0; P0=TAB[tab1]; i=1; break;
        case 1: P2=0XC0; P0=0X02; P2=0XE0; P0=TAB[tab2]; i=2; break;
        case 2: P2=0XC0; P0=0X04; P2=0XE0; P0=TAB[tab3]; i=3; break;
        case 3: P2=0XC0; P0=0X08; P2=0XE0; P0=TAB[tab4]; i=4; break;
 
        case 4: P2=0XC0; P0=0X10; P2=0XE0; P0=TAB[tab5]; i=5; break;
        case 5: P2=0XC0; P0=0X20; P2=0XE0; P0=TAB[tab6]; i=6; break;
        case 6: P2=0XC0; P0=0X40; P2=0XE0; P0=TAB[tab7]; i=7; break;
        case 7: P2=0XC0; P0=0X80; P2=0XE0; P0=TAB[tab8]; i=0; break;
    }
}
 
void key_scan()//半矩阵键盘扫描,常用需要理解记住
{
    key = 0;
    P44=1; P42=1; P3=0X00;
    if((P44==0)|(P42==0))//判断竖行
    {
        delay(2);//消抖
        P44=1; P42=1; P3=0X00;
        if((P44==0)|(P42==0))
        {
            if(P44==0) key = 4;
            if(P42==0) key = 8;
        }
        P44=0; P42=0; P3=0X3F;
        if(P3!=0X3F)//判断横行
        {
            P44=0; P42=0; P3=0X3F;
            delay(2);//消抖
            if(P3!=0X3F)
            {
                if(P33==0) key += 0;
                if(P32==0) key += 1;
                if(P31==0) key += 2;
                if(P30==0) key += 3;
            }    
        }
        while(P3!=0X3F);//判断抬手
    }
}
 
void time_read()//时间读取函数,需要赋值几个变量,所以放在主函数写
{    
    EA = 0;//使用时间读取,需要关闭中断
    Write_Ds1302_Byte(0x8e,0x00);
    sec = Read_Ds1302_Byte(0x81);
    min = Read_Ds1302_Byte(0x83);
    hour = Read_Ds1302_Byte(0x85);
    Write_Ds1302_Byte(0x8e,0x80);
    EA = 1;//写完后,打开中断
}
 
void time_display()//时间显示函数,里面附加调整参数,里面附加切换按键
{
    if(key==4)//功能按键,切换显示功能
    {
        if(T_set==0) { T_set = 1; hour_tem = hour, min_tem = min, sec_tem = sec; }//临时赋值时间,好处,调整时间的时候,时间显示不会正常走时
        else if(T_set==1) T_set = 2;//1-3循环,依照题目的要求,只有按下S7的时候,保存数据
        else if(T_set==2) T_set = 3;
        else if(T_set==3) T_set = 1;
    }
    else if(key==10)//减按键
    {
        if(T_set==1) { if(hour_tem==0) hour_tem=1; hour_tem--; }//注意设置范围
        else if(T_set==2) { if(min_tem==0) min_tem=1; min_tem--; }
        else if(T_set==3) { if(sec_tem==0) sec_tem=1; sec_tem--; }
    }
    else if(key==11)//加按键
    {
        if(T_set==1) { hour_tem++; if(hour_tem==24) hour_tem=23;}//注意设置范围
        else if(T_set==2) { min_tem++; if(min_tem==60) min_tem=59;}
        else if(T_set==3) { sec_tem++; if(sec_tem==60) sec_tem=59;}
    }
 
    if(T_set==0)//正常时间显示
    {
        tab1=hour/10; tab2=hour%10; tab3=11; tab4=min/10; tab5=min%10; tab6=11; tab7=sec/10; tab8=sec%10;
    }
    else if(T_set==1)//时间调整
    {    //所调整的值闪烁
        if(sec%2==0) { tab1=hour_tem/10; tab2=hour_tem%10; tab3=11; tab4=min_tem/10; tab5=min_tem%10; tab6=11; tab7=sec_tem/10; tab8=sec_tem%10; }
        else { tab1=10; tab2=10; tab3=11; tab4=min_tem/10; tab5=min_tem%10; tab6=11; tab7=sec_tem/10; tab8=sec_tem%10; }
    }
    else if(T_set==2)//分钟调整    
    {
        if(sec%2==0) { tab1=hour_tem/10; tab2=hour_tem%10; tab3=11; tab4=min_tem/10; tab5=min_tem%10; tab6=11; tab7=sec_tem/10; tab8=sec_tem%10; }
        else { tab1=hour_tem/10; tab2=hour_tem%10; tab3=11; tab4=10; tab5=10; tab6=11; tab7=sec_tem/10; tab8=sec_tem%10; }
    }
    else if(T_set==3)//秒调整
    {
        if(sec%2==0) { tab1=hour_tem/10; tab2=hour_tem%10; tab3=11; tab4=min_tem/10; tab5=min_tem%10; tab6=11; tab7=sec_tem/10; tab8=sec_tem%10; }
        else { tab1=hour_tem/10; tab2=hour_tem%10; tab3=11; tab4=min_tem/10; tab5=min_tem%10; tab6=11; tab7=10; tab8=10; }
    }
}
void voltage_display()//电压显示函数,里面附加调整参数,里面附加切换按键
{
    if(key==4)//功能按键,切换显示功能
    {
        if(V_set==0) V_set = 1;
        else if(V_set==1) V_set = 2;
        else if(V_set==2) V_set = 1;
    }
    else if(key==10)//减按键
    {
        if(V_set==1) { if(V_h==0) V_h = 5; if(V_h>V_l) V_h-=5; }//注意设置范围,加减500mV
        else if(V_set==2) { if(V_l==0) V_l = 5; V_l-=5; }
    }
    else if(key==11)//加按键
    {
        if(V_set==1) { V_h+=5; if(V_h==55) V_h = 50; }
        else if(V_set==2) { if(V_h>V_l) V_l+=5; if(V_l==55) V_l = 50; }
    }
 
    if(V_set==0)//正常电压显示
    {
        tab1=11; tab2=1; tab3=11; tab4=10; tab5=AD/10; tab6=AD%10; tab7=0; tab8=0;
    }    
    else if(V_set==1)//调整上限电压
    {     //所调整的值闪烁
        if(sec%2==0) { tab1=V_h/10; tab2=V_h%10; tab3=0; tab4=0; tab5=V_l/10; tab6=V_l%10; tab7=0; tab8=0; }
        else { tab1=10; tab2=10; tab3=10; tab4=10; tab5=V_l/10; tab6=V_l%10; tab7=0; tab8=0; }
    }
    else if(V_set==2)//调整下限电压
    {
        if(sec%2==0) { tab1=V_h/10; tab2=V_h%10; tab3=0; tab4=0; tab5=V_l/10; tab6=V_l%10; tab7=0; tab8=0; }
        else { tab1=V_h/10; tab2=V_h%10; tab3=0; tab4=0; tab5=10; tab6=10; tab7=10; tab8=10; }    
    }    
} 
void frequ_display()//频率显示函数,里面附加切换按键
{
    if(key==4) F_T = ~F_T;//功能按键,切换显示功能
    if(F_T==0)//显示频率
    {
        tab1=11; tab2=2; tab3=11; tab4=frequ/10000; tab5=frequ%10000/1000; tab6=frequ%1000/100; tab7=frequ%100/10; tab8=frequ%10;    
    }
    else //显示周期
    {
        tab1=11; tab2=2; tab3=11; tab4=fre_time/10000; tab5=fre_time%10000/1000; tab6=fre_time%1000/100; tab7=fre_time%100/10; tab8=fre_time%10;
    }
        
}
 
void inquiry()//查询显示函数,里面附加切换按键
{
    if(key==4) inqu_state = ~inqu_state;
    if(inqu_state==0)//显示事件类型
    {
        tab1=10; tab2=10; tab3=10; tab4=10; tab5=10; tab6=10; tab7=0; tab8=thing_num;        
    }    
    else//显示发生时间
    {
        tab1=hour_in/10; tab2=hour_in%10; tab3=11; tab4=min_in/10; tab5=min_in%10; tab6=11; tab7=sec_in/10; tab8=sec_in%10;    
    }
}
 
void dat_read()//从EEPROM获取题目所需的变量
{
    if(EEPROM_read(0x01)!=3)//初始化参数,第一遍烧录程序只执行一次,比较好的模板,可记住
    {
        delay(3); 
        EEPROM_write(0x01,3); delay(3);
        EEPROM_write(0x11,20); delay(3);
        EEPROM_write(0x12,10);
    }
    delay(3);
    V_h = EEPROM_read(0x11); delay(3);//连续读取或写入,必须加小延迟
    V_l = EEPROM_read(0x12); delay(3);
    thing_num = EEPROM_read(0x20); delay(3);
    hour_in = EEPROM_read(0x21); delay(3);
    min_in = EEPROM_read(0x22); delay(3);
    sec_in = EEPROM_read(0x23); delay(3);    
}
 
void dat_gain()//定时数据获取函数
{
    if(AD_state==1) //一般可在获取数据后判断状态,保证数据正确
    {
        AD_state = 0; AD = AD_read(0x03)/5.1; //读取电压*10
        if((V_h<AD)&(times==0)) //判断超过上限
        { 
            times = 1;
            thing_num = 1;
            hour_in = hour; min_in = min; sec_in = sec;
            EEPROM_write(0x20,thing_num); delay(5); //向EEPROM写入事件类型,发生时间
            EEPROM_write(0x21,hour_in); delay(5);
            EEPROM_write(0x22,min_in); delay(5);
            EEPROM_write(0x23,sec_in); 
        }
        else if((AD<V_l)&(times==0))//判断低于下限
        {
            times = 1;
            thing_num = 0;
            hour_in = hour; min_in = min; sec_in = sec;
            EEPROM_write(0x20,thing_num); delay(5); //向EEPROM写入事件类型,发生时间
            EEPROM_write(0x21,hour_in); delay(5);
            EEPROM_write(0x22,min_in); delay(5);
            EEPROM_write(0x23,sec_in);     
        }
        else if((AD>=V_l)&(AD<=V_h)) times = 0;//判断电压是否回到正常值,times只有置零,才能开始下次判断
    }
    else if(time_state==1) { time_state = 0; time_read();}    
}
 
void key_function()//按键功能
{
    if((key==7)&(V_set==0))//时钟按键,进入相关显示函数
    {
        function = 0;
        if(T_set!=0)//判断是否处于设置界面
        {
            T_set = 0;
            EA = 0;
            Write_Ds1302_Byte(0x8e,0x00);//重新写入所设置的时间
            Write_Ds1302_Byte(0x80,sec_tem);
            Write_Ds1302_Byte(0x82,min_tem);
            Write_Ds1302_Byte(0x84,hour_tem);
            Write_Ds1302_Byte(0x8e,0x80);
            EA = 1;
        }
    }
    else if((key==6)&(T_set==0))//电压测量按键,进入相关显示函数
    {
        function = 1;
        if(V_set!=0)//判断是否处于设置界面
        {
            V_set = 0;
            EEPROM_write(0x11,V_h);//向EEPROM写入所设置的时间
            delay(3);
            EEPROM_write(0x12,V_l);
        }
    }
    else if((key==5)&(V_set==0)&(T_set==0))//频率测量按键,进入相关显示函数
    {    
        function = 2;
        if(F_T!=0) F_T = 0;//返回初始界面
    }
    else if(key==9)//查询按键,进入相关显示函数
    {
        function = 3;
        if(inqu_state!=0) inqu_state = 0;    //返回初始界面
    }
    //function   0为时间显示界面 1为电压测量界面 2为电压阈值设置界面  3为查询界面
    if(function==0)  time_display();
    else if(function==1) voltage_display();
    else if(function==2) frequ_display();
    else if(function==3) inquiry();
}    
 
 
void main()
{
    P2=0XA0; P0=0X00; P2=0X80; P0=0XFF;//初始化,熄灭灯,关闭蜂鸣器和继电器
 
    Write_Ds1302_Byte(0x8e,0x00);//写入时间 23-59-55
    Write_Ds1302_Byte(0x80,55);
    Write_Ds1302_Byte(0x82,59);
    Write_Ds1302_Byte(0x84,23);
    Write_Ds1302_Byte(0x8e,0x80);
 
    dat_read();//初始化读取
        
    timer_int();//定时器初始化
    while(1)
    {
        key_scan();//按键扫描
 
        dat_gain();//定时获取时间
        
        key_function();//按键功能
    }
}
 
void display_timer0()interrupt 1
{
    TH0 = (65535-1000)/256;//定时器1装载
    TL0 = (65535-1000)%256;
    display();//数码管扫描显示     
 
    dat_t++;//定时数据获取的时刻,定义时,记得超过256,需要定义为 unsigned int
    if(dat_t==50) AD_state = 1;
    else if(dat_t==150) time_state = 1;
    else if(dat_t==250) //打开定时器1中断,开始计数
    {    TR1 = 1; ET1 = 1; }
    else if(dat_t==280)
    {
        TR1 = 0; ET1 = 0;//关闭定时器1中断,计数完毕
        fre_time = (H_tem + L_tem)*5;//计算周期
        frequ = 1000000/fre_time;//计算频率
    }
    else if(dat_t==400) dat_t = 0;//时间最后记得清零
}
 
void frequ_time1()interrupt 3//定时器1中断,因为存在2个中断,所以有一个中断必须限制中断时长,在定时器0中断中设置30ms的使用时间
{
    if(P34==1)//判断高电平
    {
        H++;//记录高电平周期数
        if(fre_state==1)//保存一次低电平的周期数
        {
            fre_state = 0;
            L_tem = L;//赋值
            L = 0;//清零,为下次读取做准备
        }
    }
    else if(P34==0)//判断低电平
    {
        L++;//记录低电平周期数
        if(fre_state==0)//保存一次高电平的周期数
        {
            fre_state = 1;
            H_tem = H;//赋值
            H = 0;//清零,为下次读取做准备
        }
    }    
}

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/699155
  • 除此之外, 这篇博客: 将一串数字以空格间隔的方式输入,并以插入排序的方式进行升序排序,最后输出中的 题目 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 将一串数字以空格间隔的方式输入,并以插入排序的方式进行升序排序,最后输出。
    例如:
    输入:1 3 44 2
    输出:1 2 3 44

    插入排序的基本思想:每一步将一个待排序的元素按照其值的大小插入到已排序序列的适当位置上,直到待排序元素插入完为止。

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <vector>
    using namespace std;
    
    inline double stringTodouble(const string& s){
        //用于将字符串转换为double实数
        //因为要调用多次,将其置为内联函数
        double d;
        istringstream is(s);
        is>>d;
        return d;
    }
    
    void stringsplit(const string s,vector<double>& v){
        string temp;
        istringstream stream(s);
        while(stream>>temp)
            v.push_back(stringTodouble(temp));
    }
    
    void insertSort(vector<double>& V,int n){
        //将当前移动的数从后面开始对比,逐步前移
        int i,j;
        for(i=1;i<n;i++){
            j=i;
            double temp=V[i];
            while(j>0 && temp<V[j-1]){
                V[j] = V[j-1];  //后移
                j--;
            }
            V[j] = temp;
        }
    }
    
    void printSort(const vector<double> v){
        cout<<"排序后的结果是:";
        for(int x=0;x<v.size();x++)
            cout<<v[x]<<" ";
    }
    
    int main()
    {
        string str;
        vector<double> v;
        cout<<"输入数字进行插入排序:"<<endl;
        getline(cin,str);
        stringsplit(str,v);         //将数从字符串分割后放入容器
        insertSort(v,v.size());     //进行插入排序
        printSort(v);               //输出排序后的序列
        cout<<endl;
        return 0;
    }
    
  • 您还可以看一下 金圣韬老师的数字图像处理实战课程中的 交通标志牌识别及基于光流的车速估计小节, 巩固相关知识点