阿杰爱学单片机 发表于 2024-8-26 10:07:45

本帖最后由 阿杰爱学单片机 于 2024-8-26 10:10 编辑

第五集 上(求助贴2)

在这次的学习中,我们跟着冲哥学习使用C语言中的printf打印输出字符串到串口‘’ 但在这之中我又遇到了问题。

第一个问题,printf不是C语言中的函数吗,怎么就直接运用到单片机上了
第二个问题,按道理来说串口应该做一些处理才能输出数据吧,而视频里,直接就使用printf就能输出字符了这让我非常不解
第三个问题,随后我又去看了下布丁橘子长的代码,发现他写的和冲哥的代码完全是两种,他的代码不仅应用了<stdio.h>的头文件,还重构了pintf的底层代码,还用了定时器,看起来很复杂,冲哥却只加几行代码就实现了,搞不懂
第四个问题,冲哥的视频中,都没有应用<stdio.h>的头文件为啥就可以用pintf了?




电子DIY小家 发表于 2024-8-26 10:32:56

第一个问题,printf不是C语言中的函数吗,怎么就直接运用到单片机上了
------这个单片机就是C语言开发的呀,printf是C标准库里的功能,单片机当然也可以调用

第二个问题,按道理来说串口应该做一些处理才能输出数据吧,而视频里,直接就使用printf就能输出字符了这让我非常不解
------视频里调用的是现成的库,在库里面设置好了底层的串口(USB-CDC串口),所以只要初始化之后就可以直接使用了

第三个问题,随后我又去看了下布丁橘子长的代码,发现他写的和冲哥的代码完全是两种,他的代码不仅应用了<stdio.h>的头文件,还重构了pintf的底层代码,还用了定时器,看起来很复杂,冲哥却只加几行代码就实现了,搞不懂
------视频里调用的是现成的库,在库里面设置好了底层的串口(USB-CDC串口),这一节只是最简单的调用,到了后面讲CDC串口的时候会重点讲这个的,这一章只要求学会怎么printf打印数据,不然后面几个章节的内容看不了数据,不好验证

第四个问题,冲哥的视频中,都没有应用<stdio.h>的头文件为啥就可以用pintf了?
------你可以打开底层的.H文件去看看,在别的文件里调用了<stdio.h>的

阿杰爱学单片机 发表于 2024-8-26 10:48:50

我又改了这回更离谱了,我把冲哥的代码和文件(COMM)复制到我的工程,然后发现还是不行,但我试了一下他的工程是没问题的,
但我复制过来就有问题,是不是那里没设置好

阿杰爱学单片机 发表于 2024-8-26 10:52:00

电子DIY小家 发表于 2024-8-26 10:32
第一个问题,printf不是C语言中的函数吗,怎么就直接运用到单片机上了
------这个单片机就是C语言开发的呀 ...

我用的是<STC32G.h>我还以为<STC32G.h>和"STC.h"是一样的,回头看了一下确实包含了

阿杰爱学单片机 发表于 2024-8-26 10:57:03

电子DIY小家 发表于 2024-8-26 10:32
第一个问题,printf不是C语言中的函数吗,怎么就直接运用到单片机上了
------这个单片机就是C语言开发的呀 ...

我把我的代码复制到他的工程里,屏蔽了它的代码,发现我的代码奇迹般的运行成功,我是不是Keill哪里又设置错了

阿杰爱学单片机 发表于 2024-8-26 11:06:05

阿杰爱学单片机 发表于 2024-8-26 10:57
我把我的代码复制到他的工程里,屏蔽了它的代码,发现我的代码奇迹般的运行成功,我是不是Keill哪里又设 ...

OK已经解决了,KEIll里面那个memory model 弄错了弄成了XSmall data了,这个是储存方式吗

阿杰爱学单片机 发表于 2024-8-26 16:32:33

本帖最后由 阿杰爱学单片机 于 2024-8-30 14:02 编辑

第五集 下

本次跟着冲哥学习了c语言中的各种运算,包括+-*/%&|~,加减乘除按位与按位或,还有取反的用法,这么一说想起之前的一个问题,一直没有研究就是!和~有啥区别 ,有时候用这两个都可以。
还学习了进制的转换,这里给大家一个小技巧2进制转16进制的一个小技巧,就是8421码,具体可以去搜一下,二进制一般八位数表示16进制两位数,举个例子
1010 1011
8421 8421
从高位到低位一 一对应只要是零的地方就去掉对应的8421码
1010 1011
8 2   821
就比如这样,然后每组相加最后得到结果
1010 1011
    10    11
每四个二进制对应一个16进制数的一位
然后10对应16进制A,11对应16进制B    16进制数排序(123456789ABCDEF)
最后得出的结果就是16进制数的0xAB
具体方法可以去搜一下。

这次代码总体没问题,输出英文,数字没啥问题,但是输出中文就乱码了,又让人头疼了,有大佬指点下吗
问题已经解决,在串口助手,选择,串口设置,UTF8编码格式






阿杰爱学单片机 发表于 2024-8-26 19:18:16

本帖最后由 阿杰爱学单片机 于 2024-8-26 19:43 编辑

第6集 学习记录

这集讲到了

delay 函数的书写
以及如何使用delay函数实现LED闪烁,原理就是通过执行一些循环的操作,让程序卡在某个地点,达到延时的效果,缺点显而易见,影响程序的执行速度。


宏定义#define
可以理解为就是给一个变量或者寄存器取个新名字,名字写在左边,右边写变量或者.....比如
#defineaa   1234
优点就是当需要改变某个值的时候直接修改宏定义就好,使代码更加高效

typdef的应用
以我的理解,就是给,变量类型名取新名字,他和宏定义的区别是他只能给变量类型取名字
而宏定义,就不管那么多了。
假如一个变量类型的名字太长了,可以给他取一个新名字,便于书写,也便于自己理解。使用方法
typdefunsigned char u8;
typdefunsigned int u16;


函数的书写和返回值和参数比如
void XX()空返回值类型
{}
int XX()int型返回值类型,有返回值的函数还需要写上return
{return;}
void XX(char XX)这里的char是形参
{}

讲到了模块化编程,
可以使代码更加精简,不容易出错,有利于团队合作,需要创建一个c文件还有一个h文件。

c文件里写上函数和头文件
.h文件里写上函数声明如下

#ifndef __XXX_H__
#define __XXX_H__

void XXX(char XXX);
float XXX (int XXX);

#endif

如果新建的文件是在文件夹里还要声明以下路径才可以应用
引用时只需调用对应的头文件即可




最后冲哥布置了一个作业,我是这么写的没有问题
void main(void)      //主函数(程序从这里执行)
{
      SYS_Init();                                        // STC32初始化
      MyUSB_Init();                              //USB初始化
      GPIO_Init();                              //IO口初始化
      while(1)
      {
                if( DeviceState != DEVSTATE_CONFIGURED )         //
                        continue;
                if( bUsbOutReady )                                                               
                {
                        usb_OUT_done();
                }

                for(i=0;i<6;i++)
                {
                        if(i<3)
                        {
                              P20=0;
                              delay_ms(200);
                              P20=1;
                              delay_ms(200);
                        }
                        else
                        {
                              P20=0;
                              delay_ms(800);
                              P20=1;
                              delay_ms(800);
                        }
                }
      }
}

llyymm 发表于 2024-8-27 08:15:29

阿杰爱学单片机 发表于 2024-8-26 09:52
栓Q

{:4_245:}{:4_268:}

阿杰爱学单片机 发表于 2024-8-27 09:56:21

本帖最后由 阿杰爱学单片机 于 2024-8-27 10:40 编辑

第七集 学习记录

按键的应用,按键在生活中极为广泛是人与计算机进行交互的媒介,就比如电脑上的键盘
但在实际引用中,因为按键是机械元件,开关都会有抖动,如下图所示,此时我们就要滤除这些不必要的抖动,以免对程序效果产生影响。

按键的消抖分为软件消抖和硬件消抖
软件消抖的本质就是不读取抖动的电平,加延时耗过去。
而硬件消抖对硬件要求太高,会很麻烦,实际应用不多。

在实验中我发现冲哥的代码有一些小瑕疵,冲哥的代码只对按键按下去除抖动,而按键松开没有进行延时去抖。
就导致了有时按键松开会执行两次按键按下的语句,造成一点小影响,虽然影响不大,到我觉得保险起见,按键松手时也加入延时代码,使按键检测更准确
就如下所示这样书写。

if(Key1 == 0)                              //如果按键1按下
{
      delay_ms(10);                        //延时消抖
      while(Key1 ==0);//如果按键1按下死循环,等待松手
      delay_ms(10);                        //延时消抖
      LED1=!LED1;                        //LED1状态取反
      printf("按键1按下LED取反%\r\n");
}


串口打印小细节,不能显示中文的改一下串口设置,打开串口,点击更多设置,点击编码格式,选择UTF8就可以打印中文了


再提一点,按键控制LED左移其实有个更简单的方法
前面不是学过<<,>>,~,左移右移还有取反的运算符吗,把这些应用在一起如下
u8 i;
if(Key==0)
{
    delay_ms(10);
    while(Key==0);
    delay_ms(10);
    P2=~(0x01<<++i);

    if(i==9)i=1;
}

这句代码啥意思呢,意思就是,按键按下i++;0x80左移i位,简化一下就是按键按下几次0x01就移几位,
那0x01是啥呢,0x01换算成2进制就是0000 0001,又因为左移会把高位忽略,低位补0,所以效果就是
0000 0001
0000 0010
0000 0100
0000 1000
0001 0000.......

我们发现这个一是一只向左移的,那如果用这个一点亮LED那不就是流水灯的效果了吗。
但是我们知道开发板上的LED都是接低电平才会点亮也就是0,那用这个代码不全反了啊
这时候我们只用~这个符号,取反一下,0就变成1,1就变成0,程序就对了,最后再把这个值赋值给P2口就可以了

至于那个 if(i==9)i=1;是防止越界的,这个u8 i;是一个无符号char型数据,需要定义为全局变量,也就是写在void main上面。

这就是我这节课的感悟






页: 1 2 [3] 4 5
查看完整版本: 杰哥的32G12K128学习记录【已送试验箱】