LED灯源程序编写与编译、UART原理

回顾: 
面试题:谈谈对嵌入式的理解 
1.明确:如何向下位机部署软件 
  1.1.明确:嵌入式开发模式,画出简要的示意图 
  1.2.看图明确接下来要完成的内容 
      上位机搭建开发环境 
          各种安装 
      搞定下位机 
              掌控硬件信息 
                  粗看 
                          三大件 
                          外围 
                  细看 
                          原理图 
                          手册 
              部署uboot 
                  TF卡 
            掌握uboot常见的命令 
                print 
                    serverip 
                    ipaddr 
                setenv 
                saveenv 
                ping 
                tftp 
                update_mmc 
                go  
                 
2.面试题:谈谈对ARM处理器裸板编程的认识 
  2.1.上来直接提出案例,阐述ARM裸板编程的流程。目前:先以LED开关灯为例,进行阐述解释说明 。
  2.2.明确相关概念 。
      计算机硬件层面包括:CPU和外设 。
      CPU一天到晚都是在跟外设进行数据通信。CPU访问外设都是以地址指针的形式访问 
  2.3.紧接着分析用户需求。 
      目前需求就是:开关灯 
  2.4.掌控LED的硬件相关信息 。
      粗看: 
          看位置 
          硬件工程师 
      细看: 
          1.LED的原理图: 
          通过原理图得到: 

          1.1.务必画出一个简要的CPU访问操作LED的示意图。

                    

          1.2.看图阐述CPU核访问LED的流程 
            CPU核以软件(地址指针)形式访问GPIO控制器内部的一大堆寄存器,本质就是给GPIO控制器发送控制操作命令 。
             
            GPIO控制器根据命令由硬件上自动操作对应的引脚(管脚)(无非就是高低电平)。 
             
            引脚的状态(高/低电平)最终影响LED的状态(亮/灭)。 
          1.3.结论: 
                  接下来只要掌握GPIO控制器以及内部的一大堆寄存器的操作即可完成最终的LED的操作。 
                   
          2.问:GPIO控制器以及内部一大堆的寄存器如何访问呢? 
            答:由于GPIO控制器集成在S5P6818处理器的内部。要想知道GPIO控制器如何访问操作,只需看S5P6818处理器的芯片手册(说明书)。
        
        3.打开S5P6818处理器的芯片手册: 
          resource/Datasheet/SEC_S5P6818X_Users_Manual_preliminary_Ver_0.00.pdf 
          切记:尤其是处理器的芯片手册,只看跟目前研究的内容(GPIO控制器)相关的章节。 

          结论:P739第16章讲解GPIO控制器


          3.1.看GPIO控制器相关的说明,罗列重要的跟将来软件操作相关的内容:
              1.S5P6818包含160个GPIO引脚 
                分五组:A/B/C/D/E 
                每一组:32个GPIO 
                LED1对应的引脚为:GPIOC12(C组的第12个引脚) 
              2.GPIO的输出操作,P742 
                GPIO复用功能选择寄存器:指定GPIO引脚的复用功能 。
                GPIO输出使能寄存器:指定GPIO的输入或者输出功能 。
                GPIO输出寄存器:指定GPIO的输出值(0:低电平;1:高电平) 。
                结论:开关灯操作: 
                1.首先配置GPIO复用功能选择寄存器,配置为GPIOC12这种功能 。
                2.然后配置GPIOC12为输出功能,配置GPIO输出使能寄存器 。
                3.最后: 
                  开灯:配置GPIO输出寄存器为0 
                  关灯:配置GPIO输出寄存器为1 
                4.问:以上三个寄存器如何访问操作呢? 
                  答:寄存器也是硬件,它同样是外设! 
             3.相关寄存器的特性(P745): 
               GPIOCOUT:输出寄存器 
               基地址:0xC001C000 
               BIT[12]=0:输出低电平,开灯 
               *(volatile unsigned long *)0xC001C000 &= ~(1 << 12);                     
               美化: 
               #define GPIOCOUT *(volatile unsigned long *)0xC001C000
               GPIOCOUT &= ~(1 << 12); 
                
               BIT[12]=1:输出高电平,关灯 
               GPIOCOUT |= (1 << 12); 
                
               GPIOCOUTENB:输出使能寄存器 
               基地址:0xC001C004 
               BIT[12]=1:配置为输出功能 
               #define GPIOCOUT (*(volatile unsigned long *)0xC001C004) 
               GPIOCOUTENB |= (1 << 12); 
                
               GPIOCALTFN0:复用功能选择寄存器0(P757) 
               基地址:0xC001C020 
               BIT[25:24]=01   //注意在P68  
               GPIOCALTFN0 &= ~(3 << 24); 
               GPIOCALTFN0 |= (1 << 24);  
                
               至此:硬件信息的掌控完毕! 
                
      2.5.一旦硬件信息掌控完毕,编写LED的操作软件 
          1.明确:嵌入式软件开发分为两类 
            裸板程序: 
                    下位机不会运行操作系统(linux/windows/vxworks),运行的程序就一个,单任务运行 。
                    标准C的库函数一律不能使用,例如:printf。 
                     
            基于操作系统程序:后续慢慢讲解 
            结论:首先要明确LED的程序属于哪类。此时此刻,此LED程序为裸板程序。          
           
          2.明确:裸板程序的编程框架 
            开发语言:一般C语言或者汇编 。
            “硬件初始化”:硬件外设正式工作之前,将其工作参数,工作状态配置完毕 。
            框架: 
            //裸板程序的入口函数名随便定义,不一定非要是main 
            void xxx(void) { 
                     
                    //硬件初始化函数 
                    xxx_init(); 
                    /* 
                    led_init(); //初始化LED 
                    uart_init(); //初始化串口 
                    net_init(); //初始化网络 
                    mmc_init(); //初始化EMMC 
                    bt_init(); //初始化蓝牙 
                    lcd_init(); //初始化LCD显示屏 
                    ... 
                     
                    */ 
                     
                    while(1) { 
                         //做业务:根据用户需求,操作硬件外设 
                         /* 
                           led_on(); 
                           delay(); 
                           led_off(); 
                           delay(); 
                         */ 
                    } 
            }        
               
          3.编写LED裸板程序,实现交替闪烁 
            实施步骤: 
            上位机执行: 
            sudo chown tarena /opt -R 
            sudo chgrp tarena /opt -R 
            mkdir /opt/arm/day03/1.0 -p 
            cd /opt/arm/day03/1.0 
            vim led.h //声明 
            vim led.c //定义 
                    
                   注意:vim的使用 
                   1.vim多屏显示(命令行模式下) 
                 vs 文件名 //左右分屏 
                 sp 文件名 //上下分屏 
                 切换快捷键:ctrl + ww 
          
                 复制粘贴: 
                 shift+v:行选 
                 ctrl+v:列选 
          
                         
           
          4.问:如何编译LED的程序呢? 
            答:明确:势必不能用gcc编译(针对于X86架构),所以:务必先在上位机部署添加交叉编译器。 
                上位机添加ARM架构交叉编译器的流程: 
                4.1.获取交叉编译器 
                resource/编译器/arm-cortex_a9-eabi-4.7-eglibc-2.18.tar 
                拷贝到linux和windows共享目录中 
                cp arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz /opt/ 
                 
                4.2.上位机添加 
                cd /opt/ 
                tar -xvf arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz 
                得到新目录:arm-cortex_a9-eabi-4.7-eglibc-2.18 
                mv arm-cortex_a9-eabi-4.7-eglibc-2.18 toolchains 
                ls /opt/toolchains/bin/ 
                   arm-cortex_a9-linux-gnueabi-gcc //ARM架构的gcc编译器
                 
                sudo vim /etc/environment 
                在PATH中添加/opt/toolchains/bin,例如: 
                PATH=/opt/toolchains/bin:... 
                保存退出 
                 
                重启上位机linux系统 
                 
                4.3.测试交叉编译器 
                上位机执行: 
                arm-cortex_a9-linux-gnueabi-gcc -v //查看交叉编译器的版本 
                 
                4.4.交叉编译LED程序 
                cd /opt/arm/day03/1.0 
        arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c
                说明: 
                -nostdlib:告诉编译器,此程序不使用标准C库 
                -c:只编译不链接 

                 

arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib  -Ttext=0x48000000  -o  led.elf led.o

                说明: 
                arm...ld:链接器 
                -nostartfiles:告诉链接器,此代码无需启动文件 
                -Ttext=0x48000000:告诉链接器,代码段的起始地址为0x48000000(下位机的内存地址) 
                                -o led.elf:链接生成ELF格式的可执行文件 
                                切记:此时此刻led.elf不能在没有操作系统的环境中运行 
                                 
                                arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin
                                说明:利用arm...objcopy工具将ELF格式的可执行文件 
                                      再次获取到其中的真正的二进制文件信息 
                                      led.elf:橘子(带皮) 
                                      led.bin:果肉 
                                      objcopy:去皮工具 
                                       
                                cp led.bin /tftpboot //拷贝到下载目录 
                                 
                                绝招:反汇编 
                     arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis  
                                led.dis:反汇编文件 
                                vim led.dis //只需关注一个内容即可 
                                <0x48000000>:led_test  
                        如果看到以上信息说明:led_test函数的地址为0x48000000。说明程序的编译是对的! 
                                 
                         5.下位机测试 
                           重启下位机,进入uboot命令行模式,执行: 
                           ping 192.168.1.8 
                           tftp 48000000 led.bin 
                           go 48000000 
                         
                         6.验证入口地址特性 
                           cd /opt/arm/day03/1.0 
                           vim led.c //将delay函数的定义放在led_test函数定义的前面 
                           保存退出 
                           ①.arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c
                           ②.arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib  
                                       -Ttext=0x48000000 -o led.elf led.o 
                           ③.arm-cortex_a9-linux-objcopy -O binary led.elf led.bin
                           ④.arm-cortex_a9-linux-objdump -D led.elf > led.dis 
                           ⑤.vim led.dis  

                           查看0x48000000这个地址对应的函数是:led_test?delay? 
                            
                           切记:编译器链接是从文件的头到尾进行链接(从上到下) 
                            
                           作业:实现一个跑马灯 
                           LED1亮->LED2亮->LED3亮->LED4亮->LED1灭->... 
                            
                           作业:实现蜂鸣器的操作 
************************************************ 
2.面试题:谈谈对UART的理解 
  2.1.首先要交待计算机中常见的几种硬件通信方式 
      硬件通信接口 
      明确:计算中包括:CPU和外设。 
            CPU一天到晚和外设进行数据交互通信 
      问:CPU和外设数据通信的方式方法有哪些呢? 
      答:计算机中CPU和外设进行硬件通信的方式 
          通信接口有以下几种: 
          1.GPIO通信方式,例如:LED灯,蜂鸣器等 。
          2.UART串口通信方式,例如:GPS,GPRS,BT等 。
          3.I2C总线通信方式,例如:重力传感器,三轴加速度传感器,触摸屏等 。
          4.SPI总线通信方式,例如:Norflash闪存,触摸屏等 。
          5.1-Wire(一线式)总线通信方式,例如:温度传感器,EEPROM存储器等 。
          所以:这里开始讲解UART,如果可以,也可以阐述一下I2C总线 。
    
   2.2.UART串口的定义 
       定义就九个字:通用串行异步收发器 。
       进一步的对定义进行解释说明: 
       “通用”:UART串口应用非常广泛 
       ”串行“:CPU和外设进行数据通信时,只需一根信号线即可 。
              此信号线又称数据线,也就是说CPU和外设进行数据通信时,是一个bit位一个bit位的传输: 
              切记:UART数据传输从低位开始! 
              例如:CPU向BT发送一个0x95这个数据 
              数据线的操作如下: 
              高->低->高->低->高->低->低->高 
              1   0   1   0   1   0    0  1 

       顺便侃侃串行的死对头:并行 

       “并行”:CPU和外设数据传输时,需要多根信号线(数据线),8/16/32根,那么也就是一次数据传输可以同时传输8bit/16bit/32bit

       顺便再看看并行和串行的对比: 
       传输速度:一般来说并行快于串行 。
       传输距离:串行更适合远距离传输 。
       抗干扰性:串行抗干扰性更好。                                       
              
             “异步”:首先要明确:CPU的数据处理速度要远远快于外设。 
                     所以CPU和外设进行数据传输时,务必要考虑数据同步。 

                     “数据同步”:CPU向设备发送数据以后,要确保外设能够正常的将数据接收到,接收完整!

                     计算机中数据同步的方法有两种:异步和同步 。
                      
异步定义:双方在数据正式传输时,只要保证数据同步即可 。传输前和传输以后,无需考虑数据同步。异步具体如何实现数据同步关键在于协议中!这里待会儿讲讲UART的协议,即可了解何为异步!
                      
同步定义:CPU和外设进行数据传输时,如果采用同步方式保证数据同步,那么CPU和外设之间不仅仅有数据线,还需要一根时钟控制信号线,此信号线就是用来实现双方的数据同步,此时此刻,务必画图举例子说明即可!
                               参见:uart2.bmp 
                               以CPU向外设LM77发送1和0为例:
                               CPU在时钟线为电平时,将数据1放到数据线上(拉高数据线) 
                               设备就会在同周期的高电平从数据线上读取数据                                                    
                                         结论:低放高取
                                          
                收发器:接收和发送数据的硬件单元。         
                CPU给外设发送数据: 
                        CPU就是发送器,外设就是接收器。 
                外设给CPU发送数据: 
                        外设是发送器,CPU是接收器 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值