目录
计算二进制数据中有多少个位1
c语言状态机编程思想:
计算二进制数据中有多少个位1
int a = 0xF0; //a = 1111 0000 二进制表示
a = a & (a - 1); //a = 1110 0000
a = a & (a - 1); //a = 1100 0000
a = a & (a - 1); //a = 1000 0000
a = a & (a - 1); //a = 0000 0000
//上面那段代码的功能是将位为1的位从低到高逐个清零
//计算一个数里面有多少个位1
int count_bit1(int m)
{
int count = 0;
while(m)
{
m = m & (m-1);
count++;
}
return count;
}
如果一个数为2 N次方幂,那么这个数据的二进制数中只能有一个bit1,例如0001、0010、1000等,所以使用上面的操作可以判断数据是否为2的n次方幂如下程序所示:
int is_number(int num)
{
if( m & (m - 1) == 0) //说明只有1个位为1 一次即可清零
return 0;//如果一个数是2的N次方,返回0
else
return 1;//如果一个数不是2的N次方,返回1
}
c语言状态机编程思想:
传统的CPU在处理任务的时候是进行串行工作的,要使多个任务同步工作,理解同步是什么:同步指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。使用最多的同步方式就是状态机State Machine,,说白了整个CPU就是一个十分复杂的状态机,其包括指令获取、指令解码、指令执行、数据写回等等状态,需要一个相当庞大的状态机来完成所有工作的同步。再者我们使用的操作系统也是一个状态机,只是这个状态机是基于软件的状态机,而不是硬件电路上的状态机,例如创建一个任务,这个任务有挂起、运行、死亡、睡眠等状态,管理这些状态就需要一个完整的状态机实现,以保证何时、在何种条件下从当前状态跳转到另一个状态。
定时切换任务需要一个时钟源定时扫描,这个时钟可以使用处理器的定时器中断来实现,其实我们使用的嵌入式操作系统就是使用的定时器来作为系统时间基准以及任务调度的,也就是作为了操作系统的状态机的驱动时钟源。这样一来我们有了驱动状态机的时钟源,下面就可以开始状态机式的程序设计了。
下面的程序是定时器的中断服务程序:
void TIM3_IRQHandler(void)
{
TIM3->SR &= ~(1<<0); //清除中断标志位
StateMachine_Test();
}
在这个函数里面做了两件事情,清除中断标志以及调用StateMachine_Test函数,在这个函数里面完成一个状态机的功能,下面是这个StateMachine_Test函数的实现:
void StateMachine_Test(void)
{
static int state = 0;
static int count = 0;
if(state == 0)
{
if(count++ == 10)
{
count = 0;
printf("change state to 1");
state = 1;
}
}
else if(state == 1)
{
if(count++ == 10)
{
count = 0;
printf("change state to 2");
state = 2;
}
}
else if(state == 2)
{
if(count++ == 10)
{
count = 0;
printf("change state to 0");
state = 0;
}
}
}
添加内容之后的状态机变得复杂起来但其实也是很简单,这个状态机的驱动时钟源为100Hz,则每隔10ms调用一次这个状态机函数StateMachine_Test,一开始state为0,count也为0,这时候状态机处于状态0,则程序进行if(state == 0)的分支,在这里面进行count的自增操作,当count大于10也就是过了100ms之后就会将状态机的状态切换到状态1,这时候当下一次状态机运算开始时程序就会跳入if(state == 1)的分支,类似的也会从状态1调到状态2,然后从状态2跳回到状态0。这是一个简单的状态机程序,整个状态机只有三个状态,而且每个状态中的任务都十分简单,但是可以在这种状态机的思想上完成十分复杂程序设计。