C语言实现流水灯

思考:

①流水灯的实现是将控制该灯的另一端设置为低电平或者高电平(反着接入的情况下),以高电平为例;

②假如说有8个小灯,则需要将8个小灯对应的为一次设置为1,其他设置为0,因此需要循环,循环周期为8;

③将每个小灯对应位设置为1,则可以通过0x1的位置实现:0000 0001  、0000 0010 、 0000 0100.......每次多移动一位

④每个小灯点亮后需要持续一段时间,可以使用for循环的空语句,让程序在点亮一个小灯后持续一段时间,再进入下一个小灯点亮的代码之行

⑤需要将这8个小灯依次点亮后,继续这种操作,需要死循环。

代码:

#include<stdio.h>
#include<string.h>

/*
将整型数转化为二进制
*/
void intToBit(unsigned int n,char *arr){
    int totalBit = sizeof(n) * 8;
    int i = 0,j = 0;
    char ch;

    while(n / 2 != 0){
        arr[i] = '0'+ n % 2;
        n = n / 2;
        i++;
    }
    //最后一个余数处理
    arr[i] = '0'+ n % 2;

    //arr翻转
    for(j=0;j<totalBit / 2;j++){
        ch = arr[j];
        arr[j] = arr[totalBit-1-j];
        arr[totalBit-1-j] = ch;
    }
}

int main()
{
    unsigned int count = 0;
    unsigned int a = 0;
    unsigned long i;
    char arr[33] = {'\0'};



    while(1){
 //       下一个小灯点亮之前需要将数组重置为‘0’
//        for(i=0;i<8;i++){
//            arr[i] = '0';
//        }
//      可以使用库文件string.h中的memset将数组中的值初始化为'0'
        memset(arr,'0',32);

        a = 0x1<<count;

        //将十进制转化为二进制
        intToBit(a,arr);
        printf("%s\n",arr);

        count++;
        if(count == 32){
            count = 0;
        }
        for(i=0;i<300000000;i++);
    }

    return 0;
}


遇到的问题及解决办法:

1、将数字转化为字符

使用'0'字符加上这个数,因为char型字符在ASCII码表中都对应于一个整数,而数字字符在ASCII码表中是按照顺序存储的,‘0’对应的是48,‘1’对应的是49,因此将49存入到char中就代表一个字符‘1’

使用这种方法的缺点:数字字符只有‘0’~‘9’,如果是>10的数需要使用itoa或者sprintf转化,该转化只涉及0、1,所以可以不用考虑这个缺点。

'0' + 2 == '2'

2、数组赋初值

原来写的是:char arr[33] = {'\0'}或者char arr[33] = {'0'}

但是会发现,结果只能从位置为1的地方开始打印,1,10,100......但是填充的0并不能打印,

 

原因:

字符串初始化为‘\0’或者‘0’,则从第二个字符开始都是‘\0’,如果将整型转1化为二进制字符存储,{''\0','\0'......,'1'},在打印时则结果什么也打印不出来。

赋值为 '\0' 和 0 是等价的,因为字符 '\0' 在内存中就是 0。
    char str1[] = {0,0,0,0,0,1};
    printf("%s\n",str1); //什么也不显示 犹如第一个字符是'\0'
    char str2[] = {'\0','\0','\0','\0','\0',1};
    printf("%s\n",str2); //什么也不显示
    char str3[] = {'0','0','0','0','1'};
    printf("%s\n",str3); //没有结束符会出现乱码
    char str4[] = "0000000001";
    printf("%s",str4);

 

解决办法:

需要循环给数组的每个元素赋初值‘0’,在每次循环while(1)中写:

  for(i=0;i<8;i++){
     arr[i] = '0';
  }

优化:借助stdlib.h中的memset将这个数组的置零操作进行优化。

memset 一般使用“0”初始化内存单元,而且通常是给数组或结构体进行初始化。

 memset 是对较大的数组或结构体进行清零初始化的最快方法,因为它是直接对内存进行操作的。

memset(arr,'0',32);

设置32个有效字符‘0’,最后一个为结束符‘\0',不然打印会出错。


 3、延迟

使用for循环空语句进行延迟,这种延迟属于非精确延迟,单片机有自己的定时器操作。

unsigned long i;
for(i=0;i<300000000;i++);

i的值可以自己设置,注意它的数据类型,不要超出这个数据类型的表示范围。

4、未解决的问题

如何让intToBit函数的参数无论串unsigned int 或者unsigned char都可以使用呢,因为有的时候不需要32位,8位操作就可以了。

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小镇做题家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值