自己写的代码 跳跃表



public class SkipList<T> {

  //允许最大的层级s

    int maxlevel=4;
    //表头节点
    SkipListHeadNode head=new SkipListHeadNode();
    //最大层数
    int level;
    //节点长度
    int length;
    Random random=new Random();
    //抛硬币随机
    int randomLevel(){
        return random.nextInt(maxlevel)+1;
    }
    public void insertNode(int score,T value){
        int levelnum=randomLevel();//抛硬币
        System.out.println(score+","+levelnum);
        SkipListNode newnode=new SkipListNode(score, levelnum, value);
        
        //每次都在头节点添加
        //head.add(newnode);
        head.insert(newnode);
        length++;
    }
    /**
     * 查找 两个分值区间的数
     * @param startScore
     * @param endScore
     * @return
     */
    public Map<T, Integer> findRegionNode(int startScore, int endScore) {
        int currentHeadlevel = level;
        Map<T, Integer> map = new TreeMap();
        //找到最近接小于startScore节点
        SkipListNode startbeforNode;
        //开始节点 score>=startScore
        SkipListNode startNode = null;
        for (; currentHeadlevel > 0; currentHeadlevel--) {// 循环找开始节点
            SkipListNodeLevel cuurentheadlevel = head.getSkipListNodeLevel()[currentHeadlevel - 1];
            SkipListNode currheadnode = cuurentheadlevel.nextnode;
           
            if (currheadnode != null && currheadnode.score < startScore) {
                startbeforNode = currheadnode;
                 //找到最近接小于startScore节点的位置
                loopFindBeforStart(startScore, startbeforNode);
                //
                SkipListNode node = startbeforNode.getSkipListNodeLevel()[0].nextnode;
                if (node != null) {
                    startNode = node;
                }
                break;
            }

            if (currentHeadlevel == 1 && currheadnode.score < endScore) {// 最后一个
                startNode = currheadnode;
            }
        }
        if(startNode==null){
            return null;
        }
        map.put((T) startNode.value, startNode.score);
        SkipListNode hitNode=startNode.getSkipListNodeLevel()[0].nextnode;
        while(hitNode!=null&hitNode.score<=endScore){
            map.put((T) hitNode.value, hitNode.score);
            hitNode=hitNode.getSkipListNodeLevel()[0].nextnode;
        }
        
        return map;

    }
    //开始计数最接近节点
    private void loopFindBeforStart(int startScore, SkipListNode startbeforNode) {
        int hitlength = startbeforNode.getSkipListNodeLevel().length;
        for(;hitlength>0;hitlength--){
            SkipListNodeLevel currlevel=    startbeforNode.getSkipListNodeLevel()[hitlength-1];
            SkipListNode currnode=currlevel.nextnode;
            if(currnode!=null&&currnode.score<startScore){
                startbeforNode=currnode;
                loopFindBeforStart(startScore,startbeforNode);
                break;
            }
        }
    }
    
    
    public SkipListHeadNode getHead() {
        return head;
    }
    public void setHead(SkipListHeadNode head) {
        this.head = head;
    }
    
    public int getLength() {
        return length;
    }
    public void setLength(int length) {
        this.length = length;
    }


    /**
     * 头节点
     * 导航个节点的
     * @author daodao
     *
     */
    class SkipListHeadNode{
        //等级节点
        SkipListNodeLevel[] skipListNodeLevel=new SkipListNodeLevel[maxlevel];
        public void add(SkipListNode newaddNode){
            //扩容首节点长度
            if(newaddNode.getLevelNum()>level){
                level=newaddNode.getLevelNum();
            }
            
            int changelevelIndex=newaddNode.getLevelNum();
            
            SkipListNodeLevel[] headskipListNodeLevel=this.getSkipListNodeLevel();
            //设置等级指向新节点
            for(;changelevelIndex>0;changelevelIndex--){
                SkipListNodeLevel  headNodeLevel=headskipListNodeLevel[changelevelIndex-1];
                if(headNodeLevel==null){//表示该节点 目前
                    headskipListNodeLevel[changelevelIndex-1]=new SkipListNodeLevel(newaddNode,length+1);
                }else{
                    SkipListNode nextnode =headNodeLevel.getNextnode();
                    int lostspan=0;
                    setLevelNextNode(newaddNode, nextnode,lostspan);
                    break;
                }
            }
            
        }
        
        
        public void insert(SkipListNode newaddNode){
            int addnodelevelIndex=newaddNode.getLevelNum();
            SkipListNodeLevel newlevel=    new SkipListNodeLevel(newaddNode,1);
            if(length==0){
                for(;addnodelevelIndex>0;addnodelevelIndex--){
                        skipListNodeLevel[addnodelevelIndex-1]=newlevel;
                  }
            }else{
                
                for(;addnodelevelIndex>0;addnodelevelIndex--){
                   SkipListNodeLevel  headNodeLevel=skipListNodeLevel[addnodelevelIndex-1];
                   if(headNodeLevel==null){
                      skipListNodeLevel[addnodelevelIndex-1]=newlevel;
                    }else{
                        SkipListNode node=headNodeLevel.nextnode;
                        if(node.getScore()>=newaddNode.getScore())
                        {   
                            SkipListNodeLevel zhuanhuan=    skipListNodeLevel[addnodelevelIndex-1];
                            skipListNodeLevel[addnodelevelIndex-1]=newlevel;
                            newaddNode.getSkipListNodeLevel()[addnodelevelIndex-1]=zhuanhuan;
                        }else{
                            loopInsert(newaddNode, addnodelevelIndex, node,newlevel);
                        }
                    }
                }
                
            }
            
            
          if(level<newaddNode.levelNum){
              level=newaddNode.levelNum;
          }
            
        }

        //循环为每一级添加
        private void loopInsert(SkipListNode newaddNode, int addnodelevelIndex, SkipListNode node,SkipListNodeLevel newlevel) {
            SkipListNodeLevel nodelevel=node.getSkipListNodeLevel()[addnodelevelIndex-1];
            if(nodelevel==null){//在最后
                node.getSkipListNodeLevel()[addnodelevelIndex-1]=newlevel;
            }else{//在后面
                SkipListNode nextnode=nodelevel.nextnode;
                if(nextnode.getScore()>=newaddNode.getScore())
                {   
                    SkipListNodeLevel zhuanhuan=node.getSkipListNodeLevel()[addnodelevelIndex-1];
                    node.getSkipListNodeLevel()[addnodelevelIndex-1]=newlevel;
                    newaddNode.getSkipListNodeLevel()[addnodelevelIndex-1]=zhuanhuan;
                }else{
                    loopInsert(newaddNode,addnodelevelIndex,nextnode,newlevel);
                    return;
                }
            }
        }
        
        /**
         * 递归设置每一级的 nextnode
         * @param newaddNode
         * @param currnode
         * @param levelNumIndex
         */
        private void setLevelNextNode(SkipListNode newaddNode, SkipListNode currnode,int lostspan) {
            int levelNumIndex=newaddNode.getLevelNum();
            if(levelNumIndex>currnode.getLevelNum()){
                levelNumIndex=currnode.getLevelNum();
            }
            
            for(;levelNumIndex>0;levelNumIndex--){
                SkipListNodeLevel[] currentskipListNodeLevel=currnode.getSkipListNodeLevel();
                SkipListNodeLevel  ncurrLevel=currentskipListNodeLevel[levelNumIndex-1];
                
                if(ncurrLevel==null){//表示该节点 目前
                    currentskipListNodeLevel[levelNumIndex-1]=new SkipListNodeLevel(newaddNode,length+1-lostspan);
                }else{
                    lostspan=lostspan+ncurrLevel.getSpan();
                    SkipListNode newnextnode =ncurrLevel.getNextnode();
                    if(newnextnode==currnode){    
                        System.out.println("-----------"+currnode.score);
                    }
                    setLevelNextNode( newaddNode,  newnextnode,lostspan);
                    break;
                }
            }
        }


        public SkipListNodeLevel[] getSkipListNodeLevel() {
            return skipListNodeLevel;
        }

        public void setSkipListNodeLevel(SkipListNodeLevel[] skipListNodeLevel) {
            this.skipListNodeLevel = skipListNodeLevel;
        }
        
    }
    
    public void printSkipList(){
        System.out.println("-----开始遍历跳跃表-----");
        if(head==null){
            System.out.println("跳跃表没数据");
            System.out.println("-----遍历跳跃表结束-----");
            return;
        }
        
        //System.out.println(JSONObject.fromObject(this));
        
        int levelnum=level;
        int nodenum=length;
        for(;levelnum>0;levelnum--){
            System.out.print("打印第"+levelnum+"级");    
            
            SkipListNodeLevel  level=head.getSkipListNodeLevel()[levelnum-1];
            
            SkipListNode node=level.getNextnode();
            System.out.print("--"+node.score+"--"+node.value);
            
            while(node.getSkipListNodeLevel()[levelnum-1]!=null){
                 for(int i=0;i<level.getSpan();i++){
                        System.out.print("--##--");    
                    }
                node=node.getSkipListNodeLevel()[levelnum-1].nextnode;
                System.out.print("--"+node.score+"--"+node.value);
            }
            System.out.println("");    
        }
        
        
        System.out.println("-----遍历跳跃表结束-----");
    }
    
    public static void main(String[] args) {
        SkipList list=new SkipList();
        list.insertNode(4, "14");
        list.insertNode(1, "11");
        list.insertNode(3, "13");
        list.insertNode(2, "12");
        list.insertNode(5, "16cc");
        list.insertNode(7, "17");
        list.insertNode(8, "18");
        list.insertNode(6, "1666a");
       
        list.printSkipList();
        System.out.println(list.findRegionNode(2, 7));
    }
}

/**
 * 节点
 * @author daodao
 *
 */
class  SkipListNode<T>{
    //比较大小的分值 排序用
    int score;
    //保存值
    T value;
    //节点级数
    int levelNum;
    //等级节点
    SkipListNodeLevel[] SkipListNodeLevel;
    /**
     *
     * @param score 分值
     * @param levelNum 等级
     * @param value 保存值
     */
    public SkipListNode(int score,int levelNum,T value){
        this.score=score;
        this.levelNum=levelNum;
        this.value=value;
        SkipListNodeLevel=new SkipListNodeLevel[levelNum];
    }
    
    /*public querySkipListNodeLevel(int levelnum){
        SkipListNodeLevel
    }*/
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public T getValue() {
        return value;
    }
    public void setValue(T value) {
        this.value = value;
    }
    public int getLevelNum() {
        return levelNum;
    }
    public void setLevelNum(int levelNum) {
        this.levelNum = levelNum;
    }
    public SkipListNodeLevel[] getSkipListNodeLevel() {
        return SkipListNodeLevel;
    }
    public void setSkipListNodeLevel(SkipListNodeLevel[] skipListNodeLevel) {
        SkipListNodeLevel = skipListNodeLevel;
    }
    
    
}
/**
 * 等级
 * @author daodao
 *
 */
class SkipListNodeLevel{
    //下一节点
    SkipListNode nextnode;
    //跨度 没实现
    int span;
    
    public SkipListNodeLevel(SkipListNode skipListNode,int span){
        this.nextnode=skipListNode;
        this.span=span;
    }

    public SkipListNode getNextnode() {
        return nextnode;
    }

    public void setNextnode(SkipListNode nextnode) {
        this.nextnode = nextnode;
    }

    public int getSpan() {
        return span;
    }

    public void setSpan(int span) {
        this.span = span;
    }
    
   
}

<think>好的,用户之前已经问过如何使用STM32F103C8T6的PB11和PB6引脚实现超声波测距,我给出了一个分步指南。现在用户的新请求是让代码得更详细一点。我需要仔细分析用户的需求,看看他们在之前的回答中可能遗漏了什么,或者需要更详细的哪些部分。 首先,用户之前的回答已经涵盖了硬件连接、CubeMX配置、代码实现的关键部分,但可能代码部分还不够详细,尤其是对于刚接触STM32的新手来说。他们可能需要更完整的代码结构,包括初始化过程、中断配置的具体步骤,以及如何处理输入捕获的具体细节。 接下来,我需要考虑用户可能的背景。他们可能是一个学生或者刚开始学习嵌入式开发的工程师,对STM32的HAL库和CubeMX配置还不是特别熟悉。所以,在详细代码中,需要补充更多的注释,解释每一步的作用,以及如何配置定时器和GPIO。 另外,用户可能在使用过程中遇到了问题,比如不知道如何初始化定时器,或者中断处理函数的具体实现。因此,我需要确保代码示例包含完整的初始化函数,比如MX_TIM4_Init(),并且详细说明输入捕获的配置步骤,比如如何设置触发边沿和使能中断。 同时,用户可能没有正确实现延时函数,或者对如何测量回波时间的具体计算不清楚。需要补充delay_us函数的实现,可能使用定时器或者HAL_Delay的微秒级延时方法。另外,需要解释计算公式中的常数来源,比如0.034是如何得出的,以及为什么要除以2。 还需要注意用户可能忽略的细节,比如在触发信号后需要及时启动输入捕获,以及在主循环中添加超时检测,避免程序卡死在等待回波信号的情况下。此外,提到滤波算法和异常值处理,但用户可能需要具体的示例代码,比如如何实现多次测量取平均。 最后,用户可能需要更完整的代码结构,包括头文件引用、变量定义、初始化函数和主函数的具体实现。需要确保代码示例能够直接复制到项目中,并进行必要的修改以适应具体的硬件配置。</think>以下是基于STM32F103C8T6的PB11(PWM触发)和PB6(输入捕获)实现超声波测距的详细代码实现,包含完整初始化配置和注释说明: --- ### **完整代码实现** #### 1. 头文件引用与全局变量 ```c #include "main.h" #include <stdio.h> // 用于串口打印 TIM_HandleTypeDef htim4; UART_HandleTypeDef huart1; volatile uint32_t echo_start = 0; // 回波高电平起始时间 volatile uint32_t echo_end = 0; // 回波高电平结束时间 volatile float distance_cm = 0.0; // 最终距离值 volatile uint8_t echo_ready = 0; // 数据就绪标志 ``` #### 2. 微秒级延时函数 ```c void delay_us(uint16_t us) { __HAL_TIM_SET_COUNTER(&htim4, 0); // 重置定时器计数器 while (__HAL_TIM_GET_COUNTER(&htim4) < us); // 等待指定微秒数 } ``` #### 3. 触发信号生成 ```c void HC_SR04_Trigger(void) { // 发送10μs高电平脉冲 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); delay_us(10); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); } ``` #### 4. 定时器输入捕获回调函数 ```c void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM4) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET) { // 上升沿 echo_start = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 切换为下降沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); } else { // 下降沿 echo_end = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 切换回上升沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 计算时间差(处理定时器溢出) uint32_t pulse_width = (echo_end >= echo_start) ? (echo_end - echo_start) : (0xFFFF - echo_start + echo_end); distance_cm = pulse_width * 0.034 / 2; // 单位:厘米 echo_ready = 1; // 设置数据就绪标志 } } } } ``` #### 5. 主函数逻辑 ```c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM4_Init(); MX_USART1_UART_Init(); HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1); // 启动输入捕获中断 while (1) { HC_SR04_Trigger(); // 发送触发信号 echo_ready = 0; // 清除标志位 uint32_t timeout = HAL_GetTick(); // 等待测量完成(超时30ms) while (!echo_ready && (HAL_GetTick() - timeout < 30)); if (echo_ready) { printf("Distance: %.1f cm\r\n", distance_cm); } else { printf("Measurement Timeout!\r\n"); } HAL_Delay(100); // 两次测量间隔 } } ``` --- ### **CubeMX关键配置详解** #### 1. TIM4输入捕获配置(PB6) | 参数 | 值 | |--------------------|--------------------| | Clock Source | Internal Clock | | Channel1 | Input Capture direct mode | | Prescaler | 71 (72MHz→1MHz) | | Counter Period | 65535 | | Polarity | Rising Edge | | Input Filter | 0x0 (无滤波) | #### 2. GPIO配置 | 引脚 | 模式 | 参数 | |------|--------------------|-------------------------| | PB11 | GPIO_Output | Push-Pull, No pull | | PB6 | GPIO_INPUT | 外部中断模式(EXIT Line6)| --- ### **关键函数说明** #### 1. `MX_TIM4_Init()` 核心配置 ```c htim4.Instance = TIM4; htim4.Init.Prescaler = 71; // 72MHz/(71+1)=1MHz → 1μs/计数 htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 0xFFFF; // 最大计数值 htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 输入捕获通道配置 TIM_IC_InitTypeDef sConfigIC; sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_1); ``` #### 2. 中断优先级配置 ```c HAL_NVIC_SetPriority(TIM4_IRQn, 1, 0); HAL_NVIC_EnableIRQ(TIM4_IRQn); ``` --- ### **增强功能实现** #### 1. 三次采样中位值滤波 ```c #define SAMPLE_TIMES 3 float Get_MedianDistance(void) { float samples[SAMPLE_TIMES]; for (int i=0; i<SAMPLE_TIMES; i++) { HC_SR04_Trigger(); HAL_Delay(50); // 等待采样 samples[i] = distance_cm; } // 冒泡排序 for (int i=0; i<SAMPLE_TIMES-1; i++) { for (int j=i+1; j<SAMPLE_TIMES; j++) { if (samples[j] < samples[i]) { float temp = samples[i]; samples[i] = samples[j]; samples[j] = temp; } } } return samples[SAMPLE_TIMES/2]; // 返回中值 } ``` #### 2. 超时检测机制 ```c #define ECHO_TIMEOUT 30000 // 30ms超时(对应5米) // 修改输入捕获回调函数 if (htim->Instance == TIM4) { // ...原有代码... pulse_width = (echo_end >= echo_start) ? (echo_end - echo_start) : (0xFFFF - echo_start + echo_end); if (pulse_width > ECHO_TIMEOUT) { // 超时处理 distance_cm = -1.0; // 无效值标记 } else { distance_cm = pulse_width * 0.034 / 2; } } ``` --- ### **物理参数解释** 1. **0.034系数来源**: $$ \text{声速} = 340\text{m/s} = 34000\text{cm/s} = 0.034\text{cm/μs} $$ 2. **为何除以2**: 超声波经历往返路径,实际距离为: $$ \text{单程距离} = \frac{\text{总路程}}{2} $$ --- ### **常见问题排查** | 现象 | 可能原因 | 解决方案 | |--------------------|-----------------------|------------------------| | 始终返回0 | 未收到回波信号 | 检查Echo引脚连接 | | 测量值波动大 | 环境干扰 | 添加软件滤波 | | 显示超时 | 超出量程(>4m) | 检查物体是否在范围内 | | 数值跳跃 | 定时器配置错误 | 确认Prescaler设置正确 | 建议实际调试时使用逻辑分析仪抓取Trig和Echo信号波形,验证时序是否符合HC-SR04规格书要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值