2019-06-21 15:29:55 qq_38190041 阅读数 402
  • 按键和CPU的中断系统-1.8.ARM裸机第八部分

    本期课程主要讲述按键和CPU的中断系统。首先介绍了按键的电学原理,然后用2节课讲了轮询方式处理按键。之后开始了CPU中断系统的讲解,详细介绍了中断的概念和设计原理,以2440和210为原型讲解了CPU如何实现中断以及如何编程利用中断。本课程的目标是深入理解中断原理和使用轮询、中断两种方式来实现按键获取。

    6999 人正在学习 去看看 朱有鹏
单片机应用程序框架时间片轮询法的学习。

根据所见的,学的,看的。大致分为三类程序结构。
1. 简单的前后台顺序执行程序。
2. 时间片轮询法。
3. 操作系统。

简单的顺序执行的程序,写起来往往很混乱。越复杂的需求程序,完成需求的时间会更多,质量也并不好,bug也会越多,导致程序一直不能让自己满意。
为此我们需要用某个东西去管理我们的mcu中的执行逻辑。也就很容易想到用时间这条线去管理我们的逻辑。

首先我们需要构建一个结构体数据类型去管理任务

typedef struct
{
	void(*task_func)(void);   //函数指针
	uint16_t interval_time;	  //执行时间间隔
	uint16_t run_timer;		  //倒计时器
	uint8_t	 run_sign;        //程序运行标志
} schedule_task_t;

我们还得有任务

void task_1(void)
{
	printf("我是任务1");
}
void task_2(void)
{
	printf("我是任务2");;
}
void task_3(void)
{
	printf("我是任务3");;
}

然后定义一个结构体,创建任务管理配置

//创建任务配置
static schedule_task_t schedule_task[] =
{
	{task_1, 20, 20, 0}     //task_1(函数名) 20 (执行周期) 20(计时器) 0(任务执行标志)
	{task_2, 10, 10, 0},
	{task_3, 5,  5, 0}			
};

当然我们要知道任务数量,可以根据数组长度去判断

//根据数组长度,判断任务数量
#define TASK_NUM (sizeof(schedule_task)/sizeof(schedule_task_t))

我们需要一个定时器中断资源去计时。让这个定时器来管理我们的任务。所以我们需要在中断中去判断查询任务标志。

// 在中断中调用次函数判断任务标志
void task_interrupt(void)
{
	uint8_t index = 0;
	
	// 循环判断
	for (index = 0; index < TASK_NUM; index++)
	{
		// 判断计时器是否到时间
		if (schedule_task[index].run_timer)    //不为0
		{
			// 计时器减1
			schedule_task[index].run_timer--;
			//判断计时器是否到时间
			if (0 == schedule_task[index].run_timer)
			{
				// 恢复倒计时器的时间
				schedule_task[index].run_timer = schedule_task[index].interval_time;  
				// 任务标志置1
				schedule_task[index].run_sign = 1;
			}
		}	
	}
}

任务的周期由定时器去判断,管理。我们只需要在主循环中判断有无任务标志,然后执行它即可。

void task_process(void)
{
	uint8_t index = 0;
	
	// 循环判断任务
	for (index = 0; index < TASK_NUM; index++)
	{
		if (schedule_task[index].run_sign)
		{
			// 清除任务标志
			schedule_task[index].run_sign = 0; 
			// 使用函数指针,执行任务,
			schedule_task[index].task_func();
		}
	}
}
void main(void)
{
	for (;;)
	{
		task_process();
	}
}

这样就很方便的管理了我们的逻辑。也很好的理清我们的逻辑。不管移植还是需求的改动我们也很方便的去添加。

轮询
2017-11-25 17:13:50 qq_33528613 阅读数 2267
  • 按键和CPU的中断系统-1.8.ARM裸机第八部分

    本期课程主要讲述按键和CPU的中断系统。首先介绍了按键的电学原理,然后用2节课讲了轮询方式处理按键。之后开始了CPU中断系统的讲解,详细介绍了中断的概念和设计原理,以2440和210为原型讲解了CPU如何实现中断以及如何编程利用中断。本课程的目标是深入理解中断原理和使用轮询、中断两种方式来实现按键获取。

    6999 人正在学习 去看看 朱有鹏

polling
n.轮询;轮流检测,联接到另一主机查看电子信件或新闻(金山词霸)

轮询 - 百度百科
轮询(Polling)是一种CPU决策如何提供周边设备服务的方式,又称“程控输出入”(Programmed I/O)。轮询法的概念是,由CPU定时发出询问,依序询问每一个周边设备是否需要其服务,有即给予服务,服务结束后再问下一个周边,接着不断周而复始。

传统轮询、长轮询、服务器发送事件与WebSocket

Web 通信 之 长连接、长轮询(long polling)

谈谈HTTP协议中的短轮询、长轮询、长连接和短连接

2014-08-18 21:17:16 mrcaowenzheng 阅读数 2828
  • 按键和CPU的中断系统-1.8.ARM裸机第八部分

    本期课程主要讲述按键和CPU的中断系统。首先介绍了按键的电学原理,然后用2节课讲了轮询方式处理按键。之后开始了CPU中断系统的讲解,详细介绍了中断的概念和设计原理,以2440和210为原型讲解了CPU如何实现中断以及如何编程利用中断。本课程的目标是深入理解中断原理和使用轮询、中断两种方式来实现按键获取。

    6999 人正在学习 去看看 朱有鹏

时间片轮询方法


方法一:

void TimerX_handler(void)
{
    ms_cnt++;
}
初始化设置该定时器x毫秒中断一次,即ms_cnt作为一个毫秒计时器。

main(void)
{
    while(1)
    {
         if(ms_cnt%x==0)
         {
             task1();
         }
         if(ms_cnt%y==0)
         {
             task2();
         }
    }
}
主循环中,每隔x毫秒执行一次task1,每隔y毫秒执行一次task2。




方法二:


typedef _TASK_STRUCT
{
<span style="white-space:pre">	</span>u32 time_cnt;
<span style="white-space:pre">	</span>u8 run_flag;
}TASK;


TASK task1 = {x,0};
TASK task2 = {y,0};
定义任务结构体,每隔x时间置位task1执行标志位task1.run_flag,在main loop中扫描并执行;同理task2。

void TimerX_handler(void)
{
	if(task1.run_flag == 0)
		{
			task1.time_cnt--;
		}
	if(task1.time_cnt == 0)
		{
			task1.run_flag = 1;
			task1.time_cnt = x;
		}

	if(task2.run_flag == 0)
		{
			task2.time_cnt--;
		}
	if(task2.time_cnt == 0)
		{
			task2.run_flag = 1;
			task2.time_cnt = y;
		}	
}

void main(void)
{
	while(1)
		{
			if(task1.run_flag == 1)
				{
					task1();
					task1.run_flag = 0;
				}
		
			if(task2.run_flag == 1)
				{
					task2();
					task2.run_flag = 0;
				}
		}
}


(附:待完善)

2017-06-30 10:24:18 yu_jiang_2016 阅读数 1154
  • 按键和CPU的中断系统-1.8.ARM裸机第八部分

    本期课程主要讲述按键和CPU的中断系统。首先介绍了按键的电学原理,然后用2节课讲了轮询方式处理按键。之后开始了CPU中断系统的讲解,详细介绍了中断的概念和设计原理,以2440和210为原型讲解了CPU如何实现中断以及如何编程利用中断。本课程的目标是深入理解中断原理和使用轮询、中断两种方式来实现按键获取。

    6999 人正在学习 去看看 朱有鹏

        本次介绍的是一款HR7P201FHD,芯片20个脚,该芯片和普通的IC芯片类似,但是也有不同,国产,集成了触摸按键驱动程序,

可以看出该芯片的强大的性价比。

       但是凡事有利有弊,既然将触摸按键的驱动程序嵌入单片机,必然会加大单片机的负荷。每次读取按键都要包含一系列的滤波算法等的处理,并还要对该值进行快速读取。将读取的值作为一个外部接口,就是我们平时使用的按键处理了,怎么处理都好说。但是他的读取值扫描是真的很耗时间,导致做的时间时基很难做的精准,以1ms为时基,若直接放在main的大循环中,100ms的时基变成110ms都有可能,所以注定了将他们按键驱动函数,不能单纯的放在while中,否则很难保证时基。

        操作系统的轮询思想,如果大家有了解的话,应该知道:它是对系统中的每个任务进行轮询,每隔几ms或几十ms执行一次任务。任务在规定的时间内执行,看起来和直接放在普通的while循环没有什么区别,也能完成任务。其实跑操作系统和不跑操作系统的区别在什么地方呢?都是执行任务,都是一个晶振来确定时基,没有什么不同的。但是一个指令到底是多长时间,一段代码是多长时间,很多人都不会关心,而这恰恰是操作系统的产生的原因。

        当你执行任务可能上百行甚至几百行代码却只有几百us的时间的时候,你有没有想过真正运行的任务时间这么短,那么其他的时间单片机在干什么?一般的普通低端单片机时基都是以10ms等为单位的,有的时基是100ms甚至s为单位的。其实这都可以证明一件事:你的单片机并未饱和,还有些资源可以开发,他还有时间可以干其他的事,如果你想的话,可以对自己的程序进行整理,使自己的程序有条不紊,甚至达到精准。

       那么单片机平时都在干什么呢?单片机都在重复做没有必要的扫描,比如一个按键扫描可能10ms,扫描一次各个单片机的端口就够用了,因为你的按键消抖至少也是30ms以上,按键的端口扫描任务函数执行时间一般不超过100us的时间吧。而你将该任务直接放在while中轮扫,你就不是10ms扫一次,而是10ms扫描几十次甚至上百次。如果将10ms扫一次算作必要任务,并在你的while中放个空闲任务来衡量你的系统的CPU使用率,你的CPU的使用率可能不超过10%。其他的任务执行作用和空闲任务一样,空闲而已,对整个程序没有任何意义。

     所以当你定性地执行按键扫描,定性地执行任何其他任务函数,30ms执行一次按键扫描,60ms执行一次显示扫描等等,将所有的任务时间量化,就接近操作系统的轮询思想了,从程序运行上来看,你的程序具备了立体结构。重要性不同的任务执行次数应该是不一样的,重要的任务会被一直调用了,而次要的会被较少的调用,这和实际也相符合。

      系统的任务轮询,可以从思想上来改变你的程序架构,但是它也有它的局限性。比如对任务实时性任务不能做到及时的跳转,虽然他可以根据任务的重要性来决定任务的执行次数,但是他却不能中断,不能在重要的任务来临时,立即放弃当前的任务去执行重要的任务。即便是自己在给每个任务确定一定能的任务等级,但是不做中断的话,不能将当前任务压栈和保存,也得等当前任务执行完之后,才能执行下一个任务等级较高的任务。

     感觉系统永远要考虑的是时间和内存。时间越精准,要求越高。大部分的数据结果都是围绕着内存来,步步发展的。(文中有些数据未被严格地验证,但的确用示波器测过TM1629的发送很多数据80位数据,也就是几十us,看上去也是很长一段代码呀,没有等待的函数基本上都是US为单位的。)

     

2018-03-23 16:52:47 bohu83 阅读数 2624
  • 按键和CPU的中断系统-1.8.ARM裸机第八部分

    本期课程主要讲述按键和CPU的中断系统。首先介绍了按键的电学原理,然后用2节课讲了轮询方式处理按键。之后开始了CPU中断系统的讲解,详细介绍了中断的概念和设计原理,以2440和210为原型讲解了CPU如何实现中断以及如何编程利用中断。本课程的目标是深入理解中断原理和使用轮询、中断两种方式来实现按键获取。

    6999 人正在学习 去看看 朱有鹏

这里是负载均衡的常见算法。

1 轮询算法(Round-Robin)

        轮询算法是最简单的一种负载均衡算法。它的原理是把来自用户的请求轮流分配给内部的服务器:从服务器1开始,直到服务器N,然后重新开始循环。

代码:

// 轮询  
    public Server round() {  
        currentIndex = (currentIndex + 1) % totalServer;  
        return servers.get(currentIndex);  
    }  
      

其中currentindex是当前位置,totalserver是所有服务器节点数量。

优点:简单

缺点:各节点处理能力不同。

2. 加权轮询算法(WeightedRound-Robin)

        轮询算法并没有考虑每台服务器的处理能力,实际中可能并不是这种情况。由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,加权轮询算法的原理就是:根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

   这里又有两种,一种是普通加权,类似于一个数组,按权重大小排序。优先获取大权重的节点。

缺点:是不平滑。


还有一种平滑加权轮询实现,除依赖权重weight外,还依赖当前权重current_weight。是个可变数值。

思路:初始化时,获取节点的大小,及节点全部权重的最大公约数gcd,最大权重数。

 遍历列表,  获取当前权重,如果current_weight-权重最大公约数gcd<=0.则当前权重为最大权重。

  判断当前节点的权重》=当前权重,则返回对应节点,否则遍历下一个节点。

因为是循环遍历:每次从max_weight步进递减去gcd.获取出节点权重大于这个的节点。所以是平滑的,分布相对均匀的。

代码:server类 代码来自:http://m635674608.iteye.com/blog/2396303

package com.daojia.math;

public class Server {
	private String ip;  
    private int weight;  
      
    public Server(String ip) {  
        super();  
        this.ip = ip;  
    }  
  
    public Server(String ip, int weight) {  
        this.ip     = ip;  
        this.weight = weight;  
    }  
      
    public String getIp() {  
        return ip;  
    }  
    public void setIp(String ip) {  
        this.ip = ip;  
    }  
    public int getWeight() {  
        return weight;  
    }  
    public void setWeight(int weight) {  
        this.weight = weight;  
    }  
  
    @Override  
    public String toString() {  
        return "Server [ip=" + ip + ", weight=" + weight + "]";  
    }
}

主代码:

package com.daojia.math;

import java.math.BigInteger;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.concurrent.BrokenBarrierException;  
import java.util.concurrent.CyclicBarrier;  
  
public class WeightRoundRobin {  
    private List<Server> servers;  
  
    private int currentIndex;  
    private int totalServer;  
    private int currentWeight;  
    private int maxWeight;  
    private int gcdWeight;  
  
    public WeightRoundRobin() {  
        servers = new ArrayList<>();  
        servers.add(new Server("192.168.1.2", 5));  
        servers.add(new Server("192.168.1.3", 10));  
        servers.add(new Server("192.168.1.4", 15));  
        servers.add(new Server("192.168.1.5", 100));  
        servers.add(new Server("192.168.1.6", 5));  
        servers.add(new Server("192.168.1.7", 20));  
        servers.add(new Server("192.168.1.8", 30));  
        totalServer = servers.size();  
        currentIndex = totalServer - 1;  
        maxWeight = maxWeight();  
        gcdWeight = serverGcd();  
    }  
    
    /**
     * 遍历全部节点,从最大的权重开始取。
     * 每次权重-公约数递减。
     * 如果当前权重《=0.则从循环从最大权重开始。
     * @return
     */
    public Server round() {  
        while (true) {  
            currentIndex = (currentIndex + 1) % totalServer;  
            if (currentIndex == 0) {  
                currentWeight = currentWeight - gcdWeight;  
                if (currentWeight <= 0) {  
                    currentWeight = maxWeight;  
                    if(currentWeight == 0) {  
                        return null;  
                    }  
                }  
            }  
              
            if(servers.get(currentIndex).getWeight() >= currentWeight) {  
                return servers.get(currentIndex);  
            }  
        }  
    }  
  
    /** 
     * 返回所有服务器的权重的最大公约数 
     *  
     * @return 
     */  
    private int serverGcd() {  
        int comDivisor = 0;  
        for (int i = 0; i < totalServer - 1; i++) {  
            if (comDivisor == 0) {  
                comDivisor = gcd(servers.get(i).getWeight(), servers.get(i + 1).getWeight());  
            } else {  
                comDivisor = gcd(comDivisor, servers.get(i + 1).getWeight());  
            }  
        }  
        return comDivisor;  
    }  
  
    /** 
     * 获得服务器中的最大权重 
     *  
     * @return 
     */  
    private int maxWeight() {  
        int max = servers.get(0).getWeight();  
        int tmp;  
        for (int i = 1; i < totalServer; i++) {  
            tmp = servers.get(i).getWeight();  
            if (max < tmp) {  
                max = tmp;  
            }  
        }  
        return max;  
    }  
  
    /** 
     * 求两个数的最大公约数 4和6最大公约数是2 
     *  
     * @param num1 
     * @param num2 
     * @return 
     */  
    private int gcd(int num1, int num2) {  
        BigInteger i1 = new BigInteger(String.valueOf(num1));  
        BigInteger i2 = new BigInteger(String.valueOf(num2));  
        return i1.gcd(i2).intValue();  
    }  
  
    public static void main(String[] args) {  
        final WeightRoundRobin wr = new WeightRoundRobin();  
        // 非并发情况  
        for (int i = 0; i < 100; i++) {  
            System.out.println(wr.round());  
        }  
          
        System.out.println();  
        System.out.println("==========");  
        System.out.println();  
          
        final CyclicBarrier b = new CyclicBarrier(30);  
        // 并发情况  
        for (int i = 0; i < 30; i++) {  
            new Thread(new Runnable() {  
                @Override  
                public void run() {  
                    try {  
                        b.await();  
                        System.out.println(Thread.currentThread().getName() + " " + wr.round());  
                    } catch (InterruptedException | BrokenBarrierException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }, "thread" + i).start();  
        }  
    }  
  
}

运行结果:

Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.3, weight=10]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.2, weight=5]
Server [ip=192.168.1.3, weight=10]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.6, weight=5]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.3, weight=10]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.2, weight=5]
Server [ip=192.168.1.3, weight=10]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.6, weight=5]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.4, weight=15]
Server [ip=192.168.1.5, weight=100]
Server [ip=192.168.1.7, weight=20]
Server [ip=192.168.1.8, weight=30]
Server [ip=192.168.1.3, weight=10]


==========


thread27 Server [ip=192.168.1.4, weight=15]
thread0 Server [ip=192.168.1.5, weight=100]
thread4 Server [ip=192.168.1.8, weight=30]
thread1 Server [ip=192.168.1.7, weight=20]
thread29 Server [ip=192.168.1.5, weight=100]
thread28 Server [ip=192.168.1.5, weight=100]
thread25 Server [ip=192.168.1.5, weight=100]
thread24 Server [ip=192.168.1.5, weight=100]
thread21 Server [ip=192.168.1.5, weight=100]
thread20 Server [ip=192.168.1.5, weight=100]
thread17 Server [ip=192.168.1.8, weight=30]
thread16 Server [ip=192.168.1.7, weight=20]
thread13 Server [ip=192.168.1.6, weight=5]
thread12 Server [ip=192.168.1.5, weight=100]
thread9 Server [ip=192.168.1.4, weight=15]
thread8 Server [ip=192.168.1.3, weight=10]
thread5 Server [ip=192.168.1.2, weight=5]
thread2 Server [ip=192.168.1.5, weight=100]
thread3 Server [ip=192.168.1.5, weight=100]
thread6 Server [ip=192.168.1.5, weight=100]
thread7 Server [ip=192.168.1.5, weight=100]
thread11 Server [ip=192.168.1.5, weight=100]
thread10 Server [ip=192.168.1.5, weight=100]
thread14 Server [ip=192.168.1.5, weight=100]
thread15 Server [ip=192.168.1.5, weight=100]
thread18 Server [ip=192.168.1.5, weight=100]
thread19 Server [ip=192.168.1.8, weight=30]
thread22 Server [ip=192.168.1.5, weight=100]
thread23 Server [ip=192.168.1.8, weight=30]
thread26 Server [ip=192.168.1.5, weight=100]

参考:http://m635674608.iteye.com/blog/2396303

长轮询

阅读数 247

没有更多推荐了,返回首页