2019-03-26 21:25:42 HangzhouSpark 阅读数 392
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

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

网上转载:用光电式转速传感器检测转速的脉冲信息,在脉冲状态下,将转速的变化转换成光通量的变化,再通过光电转换元件将光通量的变化转换成电量的变化,接着通过频率测量电路将脉冲信号输入到单片机中,然后依据电量与转速的函数关系实现转速测量,再通过计算,从而得出里程、车速的信息,并由LED显示器显示出来。并且该电子式里程表累积的里程数字存储在非易失性的EEPROM存储器内,在无电状态下数据也能保存。

这个主要是传感器的使用,不算复杂,但是注意调通,可以找一个自行车或者共享单车的车轮做实验。

本带马工会竭尽所能解决小白入坑的问题(手动笑哭)。评论会推送至邮箱,我看见了就会回复。可接私活。
也欢迎各位大佬详细交流。

2008-04-02 10:16:00 fishtangjinfu 阅读数 1105
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

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

单片机课程设计

 

一、课程设计题:单片机教学打铃控制器程序设计

二、设计要求:

1、LED数码管显示时、分、秒时间,尽量减少时间积累误差,具有秒闪功能。

2、最多能设置40个打铃时间点,打铃时间点数据用非易失存储器存储,防止掉电丢失数据;能逐个检查、修改、删除已设置的打铃时间点和增加打铃时间点。

3、对时、打铃时间点用键盘设置,键盘设计简单、易于操作。

4、具有强电驱动功能,便于控制220V的电铃。

三、设计报告要求:

1、说明设计作品的功能、特点、应用范围;

2、方案对比,确定方案。

3、电路工作原理、操作方法;

4、编程方法、程序框图及关键程序清单。

5、课程设计总结。

 

附件:

1、参考电路图

2、24C02芯片资料及参考程序

 

                              课程设计元器件清单

元器件名

规格/型号

单板数量

购买数量

备注

电阻

510Ω1/4W

2

 

 

10K1/4W

2

 

 

1K1/4W

1

 

 

电阻排

510Ω*8

1

 

 

瓷片电容

30pF

2

 

 

独石电容

0.1µF

4

 

 

电解电容

220µF/16V

1

 

 

二极管

1N4007

1

 

 

发光二极管

Ф3MM、红光

4

 

 

三极管

9013

1

 

 

晶体

12MHz(矮封装)

1

 

 

集成块

7805

1

 

 

AT89S52

1

 

 

24C02

1

 

 

7407

1

 

 

IC插座

40PIN

1

 

 

8PIN

1

 

 

14PIN

1

 

 

数码管

2位动态、红光、共阴极(FJ5202AH

3

 

 

继电器

5VAC220V/5AHRS4H-S-DC5V

1

 

 

接插件

IDC10

1

 

 

按键

国产欧姆龙轻触按键,带透明帽

8

 

 





 



  程序:

;**************教学打铃控制器程序*********
;CPU: AT89S52, Fosc=12MHz
;++++++++++++++++++变量定义 +++++++++++++++
      SET_TIME    BIT    P1.0   ;时间设定
      SET_ALARM   BIT    P1.1   ;打铃设定
      LEFT        BIT    P1.2   ;左移位
      UP          BIT    P1.3   ;上翻/加1
      DOWN        BIT    P1.4   ;下翻/减1
      RIGHT       BIT    P1.5   ;右移位
      ESC         BIT    P1.6   ;取消/退出
      ENTER       BIT    P1.7   ;确认
      KEY_BUF     EQU    30H    ;原按键状态
      KEY_ST      EQU    31H    ;键闭合标志,ON:0FFH,OFF:00H

      SCL         BIT    P3.3   ;IIC时钟线
      SDA         BIT    P3.2   ;IIC数据线
      FLASH_S     BIT    P3.1   ;秒闪
      CONTREL     BIT    P3.4   ;控制;1=ON

      H_MEM       EQU   10H     ;时
      M_MEM       EQU   11H     ;分
      S_MEM       EQU   12H     ;秒
      CT_50MS     EQU   13H     ;50mS计数器
      NEW_TIME    EQU   14H     ;时间更新标志,0FFH更新

      DIS_MEM1    EQU   15H     ;显示数据存储器1
      DIS_MEM2    EQU   16H     ;显示数据存储器2
      DIS_MEM3    EQU   17H     ;显示数据存储器3

      DIS_BUF1    EQU   20H     ;显示缓冲器1(段码,左)
      DIS_BUF2    EQU   21H     ;显示缓冲器2(段码)
      DIS_BUF3    EQU   22H     ;显示缓冲器3(段码)
      DIS_BUF4    EQU   23H     ;显示缓冲器4(段码)
      DIS_BUF5    EQU   24H     ;显示缓冲器5(段码)
      DIS_BUF6    EQU   25H     ;显示缓冲器6(段码,右)

      AL_NUMBER   EQU   26H     ;打铃序号
      AL_TOTA     EQU   27H     ;打铃点总数
      ALARM_ST    EQU   28H     ;打铃状态,0FFH正在打铃
      TIME_OVER   EQU   29H     ;按键返回时间计数器
      TOTA_ADDR   EQU   60H     ;打铃点总数在24C02中的存储地址

        ORG     0000H

        AJMP    START
        ORG     0002BH
        AJMP    INT_T0      ;T2中断向量
        ORG     0030H

START:  MOV     SP,#60H
        CLR     CONTREL
        CLR     FLASH_S
        MOV     H_MEM,#12
        MOV     M_MEM,#0
        MOV     S_MEM,#0
        MOV     CT_50MS,#20
        MOV     NEW_TIME,#0
        MOV     KEY_ST,#0

        MOV     R4,#TOTA_ADDR  ;从24C02读打铃时间点总数
        MOV     R0,#AL_TOTA
        MOV     R3,#1
        ACALL   RD_EEROM

        MOV     A,AL_TOTA     ;总数大于0,小于、等于40判断
        JZ      JMP_RD
        CLR     C
        SUBB    A,#40
        JC      RD_AL_LIST
        MOV     AL_TOTA,#0
        MOV     R4,#TOTA_ADDR
        MOV     R3,#1
        MOV     R0,#AL_TOTA
        ACALL   WR_EEROM
        SJMP    JMP_RD
RD_AL_LIST:
        MOV     A,AL_TOTA   ;从24C02读打铃时间表
        RL      A
        MOV     R3,A
        ;R0:RAM地址指针,R2:8位移位计数器
         ;R3:数据字节计数器
        ;R4:24C02 存储地址
        MOV     R0,#80H
        MOV     R4,#00H
        ACALL   RD_EEROM

JMP_RD: MOV     TH2,#3CH      ;T2工作方式、时间常数
        MOV     TL2   , #0ABH
        MOV     RCAP2H, #3CH
        MOV     RCAP2L, #0ABH
        MOV     T2CON , #04H

        SETB    ET2           ;开中断
        SETB    EA
WAITE:  ACALL   DISPLAY
        ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#00H,KEY_MAIN
        MOV     A,NEW_TIME
        CJNE    A,#0FFH,WAITE
        MOV     NEW_TIME,#0
NEW_DIS:
        MOV     A,H_MEM
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,M_MEM
        ACALL   HBCD
        MOV     DIS_MEM2,A
        MOV     A,S_MEM
        ACALL   HBCD
        MOV     DIS_MEM3,A
        ACALL   DIS_TIME

        MOV     A,ALARM_ST
        JNZ     CHEK_OFF
        MOV     A,S_MEM
        JNZ     WAITE

        ACALL   CHEK_AL       ;打铃检测
CHEK_OFF: MOV     A,S_MEM
        CLR     C
        SUBB    A,#20
        JC      WAITE
        CLR     CONTREL
        MOV     ALARM_ST,#0
        SJMP    WAITE
        ;SJMP    $
;********打铃控制子程序***************
CHEK_AL:MOV     A,AL_TOTA
        JZ      CHEK_END
        MOV     R0,#80H
        MOV     R6,AL_TOTA
CHK_LOOP: MOV     A,@R0
        CJNE    A,H_MEM,NEXT_AL_1
        INC     R0
        MOV     A,@R0
        CJNE    A,M_MEM,NEXT_AL_2
        SETB    CONTREL
        MOV     ALARM_ST,#0FFH
        SJMP    CHEK_END
NEXT_AL_1:INC     R0
NEXT_AL_2:INC     R0
        DJNZ    R6,CHK_LOOP
        CLR     CONTREL
        MOV     ALARM_ST,#0
CHEK_END:RET
;********键盘处理程序段***************
KEY_MAIN:
        MOV     KEY_ST,#0
        JNB     SET_TIME,TIME_SET
        JNB     SET_ALARM,JMP_SET_A
        SJMP    NEW_DIS
JMP_SET_A:AJMP    ALARM_SET
;========时间设置=====================
TIME_SET:
        MOV     TIME_OVER,#30
        MOV     R5,H_MEM
        MOV     R6,M_MEM
        MOV     R7,S_MEM

SET_H:  JNB     FLASH_S,GATE_H
        MOV     DIS_MEM1,#0AAH
        SJMP    CLS_H
GATE_H: MOV     A,R5
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,R6
        ACALL   HBCD
        MOV     DIS_MEM2,A
        MOV     A,R7
        ACALL   HBCD
        MOV     DIS_MEM3,A
CLS_H:  ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_1
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_1
        AJMP    WAITE

JMP_1:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,SET_H
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#30

        JNB     UP,H_UP
        JNB     DOWN,H_DOWN
        JNB     LEFT,JMP_SET_S
        JNB     RIGHT,SET_M
        JNB     ESC,JMP_ESC
        JNB     ENTER,JMP_OK
        SJMP    SET_H

JMP_ESC:AJMP    TIME_SET_ESC
JMP_OK: AJMP    TIME_SET_OK
JMP_SET_S:
        AJMP    SET_S
H_UP:   CJNE    R5,#23,INC_H
        MOV     R5,#0FFH
INC_H:  INC     R5
        AJMP    GATE_H
H_DOWN: CJNE    R5,#0,DEC_H
        MOV     R5,#24
DEC_H:  DEC     R5
        AJMP    GATE_H
;===========分钟设置===============

SET_M:  JNB     FLASH_S,GATE_M
        MOV     DIS_MEM2,#0AAH
        SJMP    CLS_M
GATE_M: MOV     A,R6
        ACALL   HBCD
        MOV     DIS_MEM2,A
        MOV     A,R5
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,R7
        ACALL   HBCD
        MOV     DIS_MEM3,A
CLS_M:  ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_2
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_2
        AJMP    WAITE

JMP_2:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,SET_M
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#30

        JNB     UP,M_UP
        JNB     DOWN,M_DOWN
        JNB     LEFT,JMP_SET_H
        JNB     RIGHT,SET_S
        JNB     ESC,TIME_SET_ESC
        JNB     ENTER,TIME_SET_OK
        SJMP    SET_M
M_UP:   CJNE    R6,#59,INC_M
        MOV     R6,#0FFH
INC_M:  INC     R6
        AJMP    GATE_M
M_DOWN: CJNE    R6,#0,DEC_M
        MOV     R6,#60
DEC_M:  DEC     R6
        AJMP    GATE_M

JMP_SET_H:
        AJMP    SET_H
;============秒设置=================

SET_S:  JNB     FLASH_S,GATE_S
        MOV     DIS_MEM3,#0AAH
        SJMP    CLS_S
GATE_S: MOV     A,R7
        ACALL   HBCD
        MOV     DIS_MEM3,A
        MOV     A,R5
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,R6
        ACALL   HBCD
        MOV     DIS_MEM2,A
CLS_S:  ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_3
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_3
        AJMP    WAITE

JMP_3:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,SET_S
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#30

        JNB     UP,S_UP
        JNB     DOWN,S_DOWN
        JNB     LEFT,JMP_SET_S_M
        JNB     RIGHT,JMP_S_H
        JNB     ESC,TIME_SET_ESC
        JNB     ENTER,TIME_SET_OK
        SJMP    SET_S
JMP_S_H:AJMP    SET_H
S_UP:   CJNE    R7,#59,INC_S
        MOV     R7,#0FFH
INC_S:  INC     R7
        AJMP    GATE_S
S_DOWN: CJNE    R7,#0,DEC_S
        MOV     R7,#60
DEC_S:  DEC     R7
        AJMP    GATE_S
JMP_SET_S_M:
        AJMP    SET_M
;======================================
TIME_SET_ESC:
        AJMP    NEW_DIS    ;时间设置取消/返回
TIME_SET_OK:
        MOV     S_MEM,R7   ;时间设置确认/返回
        MOV     M_MEM,R6
        MOV     H_MEM,R5
        AJMP    NEW_DIS

;=========打铃设置程序段===============
ALARM_SET:
        MOV     TIME_OVER,#20
        MOV     AL_NUMBER,AL_TOTA
AL_LIST:MOV     A,AL_NUMBER
        JNZ      NUMBER_N
        MOV      DIS_MEM1,#0
        MOV      DIS_MEM2,#0AAH
        MOV      DIS_MEM3,#0AAH
        ACALL    DIS_TIME
        AJMP     WAITE_A
NUMBER_N:
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        MOV     A,AL_NUMBER
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,@R0
        ACALL   HBCD
        MOV     DIS_MEM2,A
        INC     R0
        MOV     A,@R0
        ACALL   HBCD
        MOV     DIS_MEM3,A
        ACALL   DIS_TIME

WAITE_A:ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_4
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_4
        AJMP    WAITE

JMP_4:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,WAITE_A
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#20

        JNB     UP,NUM_UP
        JNB     DOWN,NUM_DOWN
        JNB     ESC,JMP_ESC_AL
        JNB     ENTER,JMP_OK_AL
        JNB     SET_ALARM,JMP_DEL_AL
        JNB     SET_TIME,CHANGE_AL
        SJMP    WAITE_A

JMP_DEL_AL:
        AJMP    DEL_AL

;-------------------------------------
NUM_UP: MOV     A,AL_NUMBER
        CJNE    A,AL_TOTA,INC_NUM
        MOV     AL_NUMBER,#0FFH
INC_NUM:INC     AL_NUMBER
        AJMP    AL_LIST
;-------------------------------------
NUM_DOWN:MOV    A,AL_NUMBER
        CJNE    A,#0,DEC_NUM
        MOV     AL_NUMBER,AL_TOTA
        SJMP    J_DECNUM
DEC_NUM:DEC     AL_NUMBER
J_DECNUM:AJMP   AL_LIST
;==========修改打铃时间点=================
CHANGE_AL:
        MOV     A,AL_NUMBER
        JZ      JMP_ADD_AL
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        MOV     A,@R0
        MOV     R6,A
        INC     R0
        MOV     A,@R0
        MOV     R7,A
;------------时修改------------------
SET_AL_H:
        JNB     FLASH_S,GATE_AL_H
        MOV     DIS_MEM2,#0AAH
        SJMP    CLS_AL_H
GATE_AL_H:
        MOV     A,AL_NUMBER
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,R6
        ACALL   HBCD
        MOV     DIS_MEM2,A
CLS_AL_H:
        MOV     A,R7
        ACALL   HBCD
        MOV     DIS_MEM3,A
        ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_5
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_5
        AJMP    WAITE

JMP_5:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,SET_AL_H
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#20

        JNB     UP,AL_H_UP
        JNB     DOWN,AL_H_DOWN
        JNB     LEFT,SET_AL_M
        JNB     RIGHT,SET_AL_M
        JNB     ESC,JMP_AL_LIST
        JNB     ENTER,JMP_SET_AL_OK

        SJMP    SET_AL_H

JMP_ESC_AL:
        AJMP    ESC_AL
JMP_OK_AL:
        AJMP    OK_AL
JMP_ADD_AL:
        AJMP    ADD_AL
JMP_SET_AL_OK:
        AJMP    SET_AL_OK
JMP_AL_LIST:
        AJMP    AL_LIST

AL_H_UP:CJNE    R6,#23,INC_H_AL
        MOV     R6,#0FFH
INC_H_AL:INC     R6
        AJMP    GATE_AL_H
AL_H_DOWN:
        CJNE    R6,#0,DEC_H_AL
        MOV     R6,#24
DEC_H_AL:DEC     R6
        AJMP    GATE_AL_H
;----------分修改----------------
SET_AL_M:
        JNB     FLASH_S,GATE_AL_M
        MOV     DIS_MEM3,#0AAH
        SJMP    CLS_AL_M
GATE_AL_M:
        MOV     A,AL_NUMBER
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,R7
        ACALL   HBCD
        MOV     DIS_MEM3,A
CLS_AL_M:
        MOV     A,R6
        ACALL   HBCD
        MOV     DIS_MEM2,A
        ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_6
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_6
        AJMP    WAITE

JMP_6:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,SET_AL_M
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#20


        JNB     UP,AL_M_UP
        JNB     DOWN,AL_M_DOWN
        JNB     LEFT,JMP_SET_AL_H
        JNB     RIGHT,JMP_SET_AL_H
        JNB     ESC,JMP_AL_LIST
        JNB     ENTER,SET_AL_OK
        SJMP    SET_AL_M

JMP_SET_AL_H:
        AJMP    SET_AL_H

AL_M_UP:CJNE    R7,#59,INC_M_AL
        MOV     R7,#0FFH
INC_M_AL:INC    R7
        AJMP    GATE_AL_M
AL_M_DOWN:
        CJNE    R7,#0,DEC_M_AL
        MOV     R7,#60
DEC_M_AL:DEC    R7
        AJMP    GATE_AL_M

;=====打铃点设置确认/返回到列表状态======
SET_AL_OK:NOP
        MOV     A,AL_NUMBER
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        MOV     A,R6
        MOV     @R0,A
        INC     R0
        MOV     A,R7
        MOV     @R0,A
        MOV     R0,#80H
        MOV     R2,AL_TOTA
        ACALL   UP_LIST   ;调升序排序程序

        AJMP    ALARM_SET
;==========增加打铃时间点================
ADD_AL: INC      AL_TOTA
        MOV      AL_NUMBER,AL_TOTA
        MOV      R6,#08
        MOV      R7,#0
        MOV     A,AL_NUMBER
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        MOV     A,R6
        MOV     @R0,A
        INC     R0
        MOV     A,R7
        MOV     @R0,A
        AJMP     SET_AL_H
;==========打铃设置取消/返回==========
ESC_AL: MOV     R4,#TOTA_ADDR
        MOV     R0,#AL_TOTA
        MOV     R3,#1
        ACALL   RD_EEROM

        MOV     A,AL_TOTA
        JZ      EXIT_SET_AL
        RL      A
        MOV     R3,A
        MOV     R0,#80H
        MOV     R4,#00H
        ACALL   RD_EEROM
EXIT_SET_AL:
        AJMP    NEW_DIS
;=========打铃设置确认/返回===========
OK_AL:  MOV     R0,#AL_TOTA
        MOV     R3,#1
        MOV     R4,#TOTA_ADDR
        ACALL   WR_EEROM
        MOV     A,AL_TOTA
        JZ      JMP_NEW_DIS
        MOV     A,AL_TOTA
        RL      A
        MOV     R0,#80H
        MOV     R3,A
        MOV     R4,#0
        ACALL   WR_EEROM
JMP_NEW_DIS:
        AJMP    NEW_DIS
JMP_AL_SET:
        AJMP    ALARM_SET
;========删除打铃时间点===========
DEL_AL: MOV     A,AL_TOTA
        JZ      JMP_AL_SET
        JNB     FLASH_S,GATE_DIS
        MOV     DIS_MEM1,#0AAH
        MOV     DIS_MEM2,#0AAH
        MOV     DIS_MEM3,#0AAH
        SJMP    CLS_DIS
GATE_DIS:
        MOV     A,AL_NUMBER
        ACALL   HBCD
        MOV     DIS_MEM1,A
        MOV     A,AL_NUMBER
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        MOV     A,@R0
        ACALL   HBCD
        MOV     DIS_MEM2,A
        INC     R0
        MOV     A,@R0
        ACALL   HBCD
        MOV     DIS_MEM3,A
CLS_DIS:ACALL   DIS_TIME
        ACALL   DISPLAY

        MOV     A,NEW_TIME
        CJNE    A,#0FFH,JMP_7
        MOV     NEW_TIME,#0
        DJNZ    TIME_OVER,JMP_7
        AJMP    WAITE

JMP_7:  ACALL   KEY_CHECK
        MOV     A,KEY_ST
        CJNE    A,#0FFH,DEL_AL
        MOV     KEY_ST,#0

        MOV     TIME_OVER,#20

        JNB     ENTER,DEL_LIST
        JNB     ESC,JMP_AL_SET_D
        AJMP    DEL_AL
JMP_AL_SET_D:
        AJMP    ALARM_SET
;------删除列表数据-----------
DEL_LIST:
        MOV     A,AL_TOTA
        DEC     A
        JZ      CLR_TOTA
        MOV     A,AL_TOTA
        CLR     C
        SUBB    A,AL_NUMBER
        JZ      NEW_LIST
        RL      A
        MOV     R3,A
        MOV     A,AL_NUMBER
        DEC     A
        RL      A
        ADD     A,#80H
        MOV     R0,A
        INC     A
        INC     A
        MOV     R1,A
MOVE_LIST_AL:
        MOV     A,@R1
        MOV     @R0,A
        INC     R1
        INC     R0
        DJNZ    R3,MOVE_LIST_AL
NEW_LIST:
        DEC     AL_TOTA
        MOV     R0,#80H
        MOV     R2,AL_TOTA
        ACALL   UP_LIST
        LJMP    ALARM_SET
CLR_TOTA:
        MOV     AL_TOTA,#0
        LJMP    ALARM_SET
;=============================================

;*************T0中断服务子程序****************
INT_T0: PUSH    ACC           ;保护现场
        PUSH    PSW
        CLR     TF2
        MOV     TL0,#0B0H     ;50mS 定时常数
        MOV     TH0,#3CH
        DJNZ    CT_50MS,CK_500MS
        MOV     CT_50MS,#20   ;DELAY 1 SECOND

        MOV     NEW_TIME,#0FFH;置秒标志

        MOV     A,S_MEM
        CJNE    A,#59,SECOND  ;判断秒=59
        MOV     S_MEM,#0FFH

        MOV     A,M_MEM
        CJNE    A,#59,MINUTE  ;判断分=59
        MOV     M_MEM,#0FFH

        MOV     A,H_MEM
        CJNE    A,#23,HOUR    ;判断时=23
        MOV     H_MEM,#0FFH

HOUR:   INC     H_MEM         ;时加1
MINUTE: INC     M_MEM         ;分加1
SECOND: INC     S_MEM         ;秒加1
        CPL     FLASH_S
        SJMP    EXIT_T0
CK_500MS:
        MOV     A,CT_50MS
        CJNE    A,#10,EXIT_T0
        CPL     FLASH_S       ;秒闪
EXIT_T0:POP     PSW           ;恢复现场
        POP     ACC
        RETI                  ;中断返回
;======================================
;*********拆字查表子程序***************
DIS_TIME:
        PUSH    ACC
        PUSH    B
        MOV     A,DIS_MEM1
        ACALL   DIS_H_L
        MOV     DIS_BUF1,A
        MOV     DIS_BUF2,B
        MOV     A,DIS_MEM2
        ACALL   DIS_H_L
        MOV     DIS_BUF3,A
        MOV     DIS_BUF4,B
        MOV     A,DIS_MEM3
        ACALL   DIS_H_L
        MOV     DIS_BUF5,A
        MOV     DIS_BUF6,B
        POP     B
        POP     ACC
        RET
;++++++++++++++++++++++++++++++++++++
DIS_H_L:MOV     B,A
        ANL     A,#0FH
        MOV     DPTR,#LEDSEG
        MOVC    A,@A+DPTR
        XCH     A,B
        SWAP    A
        ANL     A,#0FH
        MOV     DPTR,#LEDSEG
        MOVC    A,@A+DPTR
        RET
;======================================

;*********数码管扫描子程序*************
;执行时间:10mS
;++++++++++++++++++++++++++++++++++++++
DISPLAY:PUSH    ACC
        PUSH    PSW
        PUSH    00H
        MOV     P0,#0
        MOV     A,#0FEH
        MOV     R0,#DIS_BUF1
DIS_LOOP:
        MOV     P2,A
        MOV     P0,@R0
        ACALL   DLY_DIS
        MOV     P0,#0
        RL      A
        INC     R0
        JB      ACC.6,DIS_LOOP
        MOV     P2,#0FFH
        POP     00H
        POP     PSW
        POP     ACC
        RET
;-----------------------------------
DLY_DIS:PUSH    02H
        PUSH    03H
        MOV     R2,#4
DLY_LOOP:
        MOV     R3,#204
        DJNZ    R3,$
        DJNZ    R2,DLY_LOOP
        POP     03H
        POP     02H
        RET
;======================================
;*********键盘检测子程序***************
;检测有无按键按下
;键闭合标志KEY_ST,ON:0FFH,OFF:00H
;++++++++++++++++++++++++++++++++++++++
KEY_CHECK:
        PUSH    ACC
        MOV     P1,#0FFH
        MOV     A,P1
        CPL     A
        JZ      KEY_OFF
        ACALL   DISPLAY
        MOV     A,P1
        CPL     A
        JZ      KEY_OFF
        MOV     A,KEY_BUF
        CPL     A
        JNZ     KEY_OFF

        MOV     KEY_BUF,P1
        ;XRL     A,KEY_BUF
        ;JZ      KEY_OFF
        MOV     KEY_ST,#0FFH
        SJMP    EXIT_K
KEY_OFF:MOV     KEY_ST,#0
        MOV     KEY_BUF,P1
EXIT_K: POP     ACC
        RET
;=========================================
;****单字节十六进制整数转换成单字节BCD码整数****

;入口条件:待转换的单字节十六进制整数在累加器A中。
;出口信息:转换后的BCD码整数(十位和个位)仍在累加器A中,百位在R3中。
;影响资源:PSW、A、B、R3 堆栈需求: 2字节
;+++++++++++++++++++++++++++++++++++++++++
HBCD:   MOV     B,#100 ;分离出百位,存放在R3中
        DIV     AB
        MOV     R3,A
        MOV     A,#10 ;余数继续分离十位和个位
        XCH     A,B
        DIV     AB
        SWAP    A
        ORL     A,B ;将十位和个位拼装成BCD码
        RET
;=============================================

;********写24C02 EEPROM数据子程序***********
;R0:RAM地址指针,R2:8位移位计数器
;R3:数据字节计数器
;R4:24C02 存储地址
;------------------------------------------
WR_EEROM:

          NOP
W_LOOP:   ACALL    START24
          MOV      A,#0A0H
          ACALL    WBYTE
          MOV      A,R4
          ACALL    WBYTE
          MOV      A,@R0
          ACALL    WBYTE
          ACALL    STOP24
          ACALL    DISPLAY
          INC      R0
          INC      R4
          DJNZ     R3,W_LOOP

          RET


;******读24C02 EEPROM数据子程序*********
;R0:RAM地址指针,R2:8位移位计数器
;R3:数据字节计数器
;R4:24C02 存储地址
;----------------------------------------
RD_EEROM:
          NOP
R_LOOP1:  ACALL   START24
          MOV     A,#0A0H
          ACALL   WBYTE
          MOV     A,R4
          ACALL   WBYTE
          ACALL   START24
          MOV     A,#0A1H
          ACALL   WBYTE
          ACALL   RBYTE
          MOV     @R0,A
          INC     R0
          INC     R4
          DJNZ    R3,R_LOOP1
          ACALL   STOP24
          RET

;-----------------------------------
RBYTE:    NOP
          CLR     SCL
          MOV     R2,#08H
          SETB    SDA
RBY0:     CLR     SCL
          NOP
          SETB    SCL
          NOP
          MOV     C,SDA
          RLC     A
          DJNZ    R2,RBY0
          CLR     SCL
          NOP
          CLR     SCL
          SETB    SDA
          NOP
          SETB    SCL
          RET

;-------------------------------------
WBYTE:   NOP
         MOV      R2,#08H
WBY0:    CLR      SCL
         RLC      A
         MOV      SDA,C
         NOP
         SETB     SCL
         DJNZ     R2,WBY0
         CLR      SCL
         NOP
         SETB     SCL
         NOP
         JB       SDA,$
         CLR      SCL
         NOP
         RET

;---------------------------------
START24: CLR      SCL
         NOP
         SETB     SDA
         NOP
         SETB     SCL
         NOP
         CLR      SDA
         NOP
         CLR      SCL
         RET
;---------------------------------
STOP24:  CLR     SCL
         NOP
         CLR     SDA
         NOP
         SETB    SCL
         NOP
         SETB    SDA
         NOP
         CLR     SCL
         RET

;==========================================
;**********双字节数据排序子程序**************
;功能:将打铃时间表按升序排列
;入口参数:R0:数据块首地址,R2:打铃时间点数(字数)
;影响:A,B,PSW,R0,R2,R3,R4
;=============================================

UP_LIST: PUSH    ACC
         PUSH    PSW
         PUSH    B

         MOV     A,R0
         MOV     R4,A
         DEC     R2
         MOV     A,R2
         JZ      EXIT_LIST
         MOV     R3,A
         CLR     F0
LOOP:    MOV     A,R4
         MOV     R0,A
         MOV     A,R3
         MOV     R2,A
         CLR     F0
LOOP1:   ACALL   MIN_MAX
         DJNZ    R2,LOOP1
         JNB     F0,EXIT_LIST
         DJNZ    R3,LOOP
EXIT_LIST:
         POP     B
         POP     PSW
         POP     ACC
         RET
;++++++++++++++++++++++++++++++++++++++++++++++
MIN_MAX: MOV     B,R0
         INC     R0
         MOV     A,@R0
         INC     R0
         INC     R0
         CLR     C
         SUBB    A,@R0
         MOV     R0,B
         MOV     A,@R0
         INC     R0
         INC     R0
         SUBB    A,@R0
         JC      EXIT_MM
         SETB    F0
         MOV     A,@R0
         MOV     R0,B
         XCH     A,@R0
         INC     R0
         INC     R0
         MOV     @R0,A
         DEC     R0
         MOV     A,@R0
         INC     R0
         INC     R0
         XCH     A,@R0
         DEC     R0
         DEC     R0
         MOV     @R0,A

EXIT_MM: MOV     R0,B
         INC     R0
         INC     R0
         RET
;-----------------------------------------

;*******************段码表********************
LEDSEG: DB     3FH,06H,5BH,4FH,66H,6DH,7DH,07H ;'0,1,2,3,4,5,6,7'
        DB     7FH,6FH,40H                     ;'8,9,-,B,C,D,E,F'                          



 
2013-05-16 12:34:18 mybelief321 阅读数 3858
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

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

      我个人感觉UART也不算是很难,学过单片机的相信都用过UART,在这里还是说说它吧,并且在写基础实验并调试的时候,出现了一个问题,就是我们平时使用jlink调试程序都是基于在sdram中运行的,由于ram的掉电易失性,所以咱们的裸机程序根本就不能脱机工作,也即是说复位之后程序就没有了,当然,我知道可以利用以后学的知识将它下载到NAND Flash中去,这个以后再说。貌似还有一个办法,就是使用mdk直接Download到flash,不过需要什么算法之类的,这个算法我还不懂,先不管他了,先把UART的原理实验弄清楚了再说,以后学了nand flash就可以脱机工作了。

UART概述

    S3C2440通用异步收发器(UART)提供3个独立的异步串行I/O(UART0、UART1、UART2),每个端口都可以在中断或DMA模式下。也就是说,在CPU和UART之间传输数据时,UART可以产生中断或DMA请求。

    使用UART的最简单情况是只使用3根线:Tx用于数据发送,Rx用于数据接收,GND是双方地线,提供通信双方的参考电平,如图1所示:

      其中电平转换器的作用是完成通信双方之间的电平转换,这又牵扯到RS232电平和CMOS电平,咱可以不管它,可以直接假设PC机的Rx、Tx粉笔用两根线直接与SC2440的Tx、Rx相连就行了,即,PC机发送端Tx发送一个数据,S3C2440接收端Rx就能接收到该数据,反之亦然。

S3C2440处理器UART工作原理:

      S3C240的3个UART包括可编程的波特率,红外(IR)发射/接收,一个或两个停止位,5位、6位、7位或8位的数据宽度,和奇偶校验位。(不很懂是吧,其实我开始也不懂,这是什么玩意儿)

    每个UART包含一个波特率发生器、发送器、接收器和一个控制单元,如图2所示。波特率发生器的输入时钟有3种:PCLK、FCLK/n、UEXTCLK(外部输入时钟)。

 

   结合上图,数据收发原理如下:

   UART包含两种工作模式,FIFO模式和非FIFO模式。

   ●   FIFO模式数据收发过程

    发送数据:在发送数据之前,先将数据写入到发送FIFO,然后数据从发送FIFO复制到发送移位寄存器,最后将数据从数据引脚(TxDn)移出。

    接收数据:数据从RxDn引脚一位一位地接收到接收移位寄存器,然后数据从接收移位寄存器复制到接收FIFO,最后,CPU可通过数据总线从接收FIFO中读取数据,

如图2中黑色虚线所示。

   ●   非FIFO模式数据收发过程

    发送数据: 在发送数据之前,先将数据写入到发送保持寄存器,然后数据从发送保持寄存器复制到发送移位寄存器,最后将数据从数据引脚(TxDn)移出,如图2

中黑色粗实线所示。

    接收数据:数据从RxDn引脚一位一位地接收到接收移位寄存器,然后数据从接收移位寄存器复制到接收保持寄存器,最后,CPU可以从接收保持寄存器中读取数据,

如图2中黑色虚线所示。    

    注意:从图2中可以很容易看出发送FIFO和发送保持寄存器、接收FIFO和接收保持寄存器的关系。发送保持寄存器只是发送FIFO中的一个字节,接收保持寄存器只是接收FIFO中的一个字节。其实,非FIFO模式FIFO可以理解为FIFO模式的一个特例,此时,FIFO寄存器只有一个字节,而在FIFO模式时,FIFO寄存器有64个字节。

    下面就以非FIFO模式讲解,嘿嘿,其实,FIFO模式我不会用,至少是在平时的程序中没有用到。

UART引脚及相关寄存器

    S3C2440的引脚是复用的,可以通过编程将同一个引脚设置为不同的功能,UART也不例外。前文讲到在最简单的情况下,UART只需要3根线就可以实现通信功能,出去GND外,只有两根线:一根数据发送线TXD,一根数据接收线RXD。下图为S3C2440关于UART的引脚安排图:

  

   本实验咱们使用UART0,从上图可以看出,TXD0与GPH2是复用的,RXD0与GPH3是复用的。

   因此,使用UART0,首先应将GPH2设置为TXD0功能,将GPH3设置为RXD0功能:

     GPHCON&=~((3<<4)|(3<<6));        //GPH2--TXD0;GPH3--RXD0
     GPHCON|=((2<<4)|(2<<6));          //设置GPH2、GPH3为TXD0、RXD0功能

   然后是初始化与UART0相关的寄存器。

   S3C2440处理器串口具有很多功能。例如,支持FIFO模式、硬件流控、接收中断、接收超时、接收错误状态中断使能等功能。但是,对于我这样的初学入门者,不需要过多的了解这些功能,入门级的学习只需要实现如下功能:从计算机通过串口发送一个字符给S3C2440,S3C2440收到后通过串口发给计算机。

   总体来说,实现上述功能只需要初始化以下6个寄存器:ULCONn、UCONn、UBRDIVn、UTRSTATn、URXHn、UTXHn。那么咱接下来就介绍一下这些寄存器中与UART相关的位。

 

     ● ULCONn(UART LINE CONTROL REGISTER)

     主要设置数据的长度、停止位和校验位信息,这些东西很重要的奥,设置串口调试器的时候就得依据它。

   

表1   ULCONn寄存器

ULCONn

描述 初始状态

Reserved

[7]

-

0

红外模式

[6]

0:正常模式

1:红外发送/接收模式

0

校验位

[5:3]

0xx:无校验

100:奇校验

101:偶校验

000

停止位宽度

[2]

0:每帧数据有1个停止位

1:每帧数据有2个停止位

0

数据位宽度

[1:0]

00:5位     01:6位

10:7位     11:8位

00

 

     ●   UCONn(UART CONTROL REGISTER)

     主要用于设置数据发送和接收的模式,中断方式还是查询模式。

  

表2   UCONn寄存器
UCONn 描述
时钟选择

[11:10]

x0:PCLK

01: UEXTCLK

11:FCLK/n

接收模式

[3:2]

00:关闭

01:中断模式或者查询模式

发送模式

[1:0]

00:关闭

01:中断模式或者查询模式

    从表2和图2可以看出,UCONn的第10~11位用于选择波特率发生器的输入时钟。咱们接下来的实验选择的是PCLK。

    ●   UBRDIVn(UART BAUD  RATE  DIVISOR  REGISTER)

     主要用于设置波特率。

      UART模块有3个UART波特率除数寄存器:UBRDIV0、UBRDIV1和UBRDIV2。根据所需的波特率和选定的时钟源,波特率除数寄存器(UBRDIVn)的值可以用如下计算得到:

    UBRDIVn=(int)(UART clock / (baud rate×16))-1

      其中,UART clock对应着图2中波特率发生器的3种输入时钟的一个,baud  rate是用户所需要的波特率,最前面用了强制类型,将计算结果转换为整数存储在UBRDIVn中。

     例如:如果要求串口通信的波特率是115 200,波特率发生器的输入时钟选择PCLK=50MHz,那么

                   UBRDIVn=(int)(50 000 000 / (115 200×16))-1

                                   =(int)(27.1)-1

                                   =27-1

                                   =26

      ●   UTRSTATn(UART TX/RX STATUS REGISTER)

      该寄存器包含发送和接收是否完成的状态位。

表4   UTRSTATn寄存器
UTRSTATn 描述 初始状态
发送空 [2]

当发送缓冲器无有效数据且最后一字节数据被发送后,该位自动置1

0:数据发送未完成

1:发送空

1
接收数据就绪 [0]

当接收缓冲器中接收到有效数据后,该位自动置1

0:未接收到有效数据

1:接收到有效数据

0

      咱们接下来的实验中就用到这两条语句:

     while(!(UTRSTAT0&(1<<2)));    //等待发送完成

     while(!(UTRSTAT0&(1<<0)));     //查询是否接收到有效数据

     ●   URXHn(UART RECEIVE BUFFER REGISTER )

     接收数据缓冲区寄存器,8位数据长度,当接收到数据后,从CPU可以从该寄存器读取接收到的数据。

    例如:使用UART第0通道从RXD接收数据可以使用以下方法:

     unsigned char c;
     while(!(UTRSTAT0&(1<<0)));     //等待接收完毕
     c=URXH0;

     ●   UTXHn(UART TRANSMIT BUFFER REGISTER)

     发送数据缓冲区寄存器,8位数据长度,当发送数据时,将要发送的数据写入该寄存器,即可自动发送。

     例如:使用UART 第0通道发送数据可以使用以下方法:

     UTXH0=c;
     while(!(UTRSTAT0&(1<<2)));      //等待发送完成

UART基础实验

    本实验要实现的功能:PC通过串口发送一个字符给S3C2440,S3C2440收到后通过串口发给PC。该实验的文件布局图如下:

 

main.c文件内容:

 

#include"uart.h"

int main()
{   
    unsigned char a;
    Uart0_Init(115200);     //初始化并设置波特率为115 200
    while(1)
    {
        a=getc();                    //获取串口输入的字符
        putc(a);                     //PC机显示同通过串口接收到的字符
    }     
}

uart.c文件内容:

#include<s3c2440.h>
#include"uart.h"

#define PCLK   50000000
#define UART_BRD     (int)((PCLK/(baudrate*16))-1)

/***********************************************
*函数名称:void Uart0_Init(unsigned int baudrate)
*参数说明:baudrate:波特率
*返 回 值:无
*全局变量: 无
*功    能:对UART0进行初始化                         
************************************************/

void Uart0_Init(unsigned int baudrate)
{
   GPHCON&=~((3<<4)|(3<<6));  //GPH2--TXD0;GPH3--RXD0
   GPHCON|=((2<<4)|(2<<6));     //设置GPH2、GPH3为TXD0、RXD0功能
   GPHUP=0x00;                 //上拉电阻使能
   ULCON0|=0x03;              //设置数据发送格式:8个数据位,1个停止位,无校验位
   UCON0=0x05;                //发送模式和接收模式都使用查询模式
   UBRDIV0=UART_BRD;         //设置波特率,其中波特率作为一个参数传递到该初始化函数
   URXH0=0;                    //将URXH0清零
}

/***********************************************
*函数名称:void putc(unsigned char c)
*参数说明:c:通过串口接收到的字符,注意这里是8位数据
*返 回 值:无
*全局变量: 无
*功    能:将通过串口接收到的字符发送给PC机并显示在
*          串口调试工具。                
************************************************/

void putc(unsigned char c)
{
    UTXH0=c;
    while(!(UTRSTAT0&(1<<2)));    //等待发送完成
}

/***********************************************
*函数名称:unsigned char getc(void)
*参数说明:无
*返 回 值:c:通过串口接收到的字符,注意这里是8位数据
*全局变量: 无
*功    能:接收并保存通过串口输入的数据                         
************************************************/

unsigned char getc(void)
{
    unsigned char c;
    while(!(UTRSTAT0&(1<<0)));     //查询是否接收到有效数据
    c=URXH0;
    return c;
}

 uart.h文件内容:

    

#ifndef __UART_H__
#define __UART_H__

/***********************************************
*函数名称:void Uart0_Init(unsigned int baudrate)
*参数说明:baudrate:波特率
*返 回 值:无
*全局变量: 无
*功    能:对UART0进行初始化                         
************************************************/

void Uart0_Init(unsigned int baudrate);

/***********************************************
*函数名称:void putc(unsigned char c)
*参数说明:c:通过串口接收到的字符,注意这里是8位数据
*返 回 值:无
*全局变量: 无
*功    能:将通过串口接收到的字符发送给PC机并显示在
*          串口调试工具。                
************************************************/

void putc(unsigned char c);

/***********************************************
*函数名称:unsigned char getc(void)
*参数说明:无
*返 回 值:c:通过串口接收到的字符,注意这里是8位数据
*全局变量: 无
*功    能:接收并保存通过串口输入的数据                         
************************************************/

unsigned char getc(void); 

#endif

到此,UART的实验代码已经贴出来了,我将它也传到了:

http://download.csdn.net/detail/mybelief321/5388469   点击打开链接可以自行下载,下载后直接打开工程,设置好串口后,可以直接make并调试。

注意:

     ①我使用的串口调试工具为SecureCRT,其实你用哪个串口调试工具都行,主要是得设置好出啊某调制工具的波特率也为115200,要不然接收到的就是乱码,因为时序不同步。

    ②在设置的时候不要忘了把那个Ext_RAM拷贝到工程目录中,并修改为 LOAD .\uart0.axf INCREMENTAL,你只要记得.\***.axf 时刻与下图红色圈出的内容一致就行了,它就是你的工程名。

  

 

  ③记得要时钟初始化,因为咱们本实验UART的时钟源为PCLK。很简单,还是直接修改S3C2440.s中的一行代码:

  将CLOCK_SETUP     EQU     0修改为CLOCK_SETUP     EQU     1

  

 

 

 

 

 

 

 

 

2019-02-25 17:59:31 Xiaomo_haa 阅读数 246
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

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

 

在上一篇文章仅仅介绍了单字节的写入和读取https://blog.csdn.net/Xiaomo_haa/article/details/87918394

现在介绍一下多字节操作。

E2PROM多字节操作

我们知道,写数据的时候,E2PROM是先写到缓冲区,然后再“搬运到”到掉电非易失区。所以这个过程需要一定的时间,AT24C02这个过程是不超过5ms!如果在这个时候去让它应答是没有响应的! 

所以,当我们在写多个字节时,写入一个字节之后,再写入下一个字节之前,必须等待E2PROM再次相应才可以。

/*******************************************************************************
* 函数名	:E2Read
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char led
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月25日
* 功能描述:连续读取多个数据
* 备注		:buf为数据接收指针,addr为E2PROM中要读取的数据起始地址,len为读取长度
*******************************************************************************/
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{
	do{							//用寻址操作查询当前是否可进行读写操作
		IIC_Start();
		IIC_SendByte(0xa0);	    //发送器件地址
		if(IIC_WaitAck() == 1)	//应答则跳出循环,非应答则进行下一次查询
			break;
		IIC_Stop();
	}while(1);
	
	IIC_SendByte(addr);    		//写入起始地址
	IIC_WaitAck();
	IIC_Stop();
	
	
	IIC_Start();				//发送重复启动信号
	IIC_SendByte(0xa1);	
	IIC_WaitAck();
	
	IIC_SendByte((0x50 << 1) | 0x01);	//寻址器件,后续为读操作
	while(len > 1)						//连续读取len-1个字节
	{
		*buf++ = IIC_RecByte();	 //最后字节之前为读取操作并且应答
		IIC_Ack(1); 					
		len--;
	}
	*buf = IIC_RecByte();	//最后一个字节为读取操作并且非应答
	IIC_Ack(0);							
	IIC_Stop();
}


/*******************************************************************************
* 函数名	:E2Write
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char led
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月25日
* 功能描述:连续写入多个数据
* 备注		:buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度
*******************************************************************************/
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
{
	while(len--)
	{
		do{															//用寻址操作查询当前是否可进行读写操作
				IIC_Start();
				if(IIC_WaitAck() == 1)			//应答则跳出循环,非应答则进行下一次查询
					break;
				IIC_Stop();
			}while(1);
	}
	IIC_SendByte(addr++);							//写入起始地址
	IIC_WaitAck();  									//等待从机应答	
	IIC_SendByte(*buf++);							//写入一个字节数据			
	IIC_WaitAck();  									//等待从机应答		
	IIC_Stop();												//结束写操作,以等待写入完成
}

E2PROM的页写入

上面第三个我们也能感受到一次写一个字节的慢,然后等待ACK后才能写入下一个字节。效率太低!所以就诞生了分页写的模式。 
这一次我们专门成立了一个eeprom的模块。

24C02,一共是 256 个字节,8 个字节一页,那么就一共有 32 页。

分配好页之后,如果我们在同一个页内连续写入几个字节后,最后再发送停止位的时序。EEPROM 检测到这个停止位后,就会一次性把这一页的数据写到非易失区域,就不需要像上节课那样写一个字节检测一次了,并且页写入的时间也不会超过 5ms。

如果我们写入的数据跨页了,那么写完了一页之后,我们要发送一个停止位,然后等待并且检测 EEPROM 的空闲模式,一直等到把上一页数据完全写到非易失区域后,再进行下一页的写入,这样就可以在很大程度上提高数据的写入效率。
 

/*******************************************************************************
* 函数名	:E2Write_page
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char led
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月25日
* 功能描述:连续写入一页数据
* 备注		:buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度
*******************************************************************************/
void E2Write_page(unsigned char *buf, unsigned char addr, unsigned char len)
{
	while(len)
	{
		do{								//用寻址操作查询当前是否可进行读写操作
			IIC_Start();
			IIC_SendByte(0xa0);
			if(IIC_WaitAck() == 1)		//应答则跳出循环,非应答则进行下一次查询
				break;
			IIC_Stop();
		}while(1);
		
		IIC_SendByte(addr);				//写入起始地址
		IIC_WaitAck();
		
		while(len > 0)
		{
			IIC_SendByte(*buf++);		//写入一个字节数据
			IIC_WaitAck();
			len--;						//待写入长度计数递减
			addr++;						//E2PROM地址递增
			if((addr & 0x07) == 0)		//检查地址是否到达页边界,24C02每页8字节
				break;					//到达页边界时,跳出循环,结束本次写操作
		}
		IIC_Stop();
	}
}

 

 

 

2018-08-24 10:43:14 a568713197 阅读数 3606
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

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

存储器分为易失性存储器和非易失性存储器,区别在于前者掉电后数据会被清除

通常RAM(随机读取存储器)就是易失性存储器的代表,它有包含有DRAM(动态随机存储器)和SRAM(静态随机存储器),他们之前不同在于生产工艺的不同,SRAM保存数据是靠晶体管锁存的,DRAM保存数据靠电容充电来维持。SRAM的工艺复杂,生产成本高,所以贵,容量比较大的RAM我们都选用的是DRAM。但是SRAM速度较快。

他们的价格差异还是蛮大的,开发板上的1M字节的外部SRAM芯片的价格都在20元以上,这样的价格即使比起堪比金条的DDR4内存都是碾压的存在,所以说当需要大容量的外部RAM时选用DRAM是更好的选择。

Cache常见于CPU中,cache实质属于SRAM,所以是造价高,但是速度快,比DRAM快,在电脑中体现在cache(sram)比内存(dram)快,所以cache作为CPU和内存之间通信的桥梁。

那么cache是怎么加快CPU和内存的通信的呢?先了解cache是要解决CPU和内存之间的什么矛盾。矛盾在于:CPU读取速度快,而内存给的速度慢,这样CPU要接一会数据等一会,浪费了CPU处理时间。我们把CPU常读取的内存的数据放到cache中,CPU读取cahce很快,这样CPU就免了等待时间,CPU的处理速度就提高了。还有一个问题就是cache怎么知道哪些是CPU的常用数据?其实cache存储的是PU刚用过或循环使用的一部分数据,就是做一些数据的缓存。所以cache又叫缓存。

RAM既然是存储器就要传输数据,传输数据就是通信。通信又分同步通信和异步通信。前面我们所说的DRAM和SRAM都是异步通信的,速率没有SDRAM和SSRAM快。所以现在大容量RAM存储器是选用SDRAM的。S(Synchronous同步)

现在电脑里面用的内存条就是RAM。我笔记本和手机用的是DDR4SDRAM,我的嵌入式开发板用的是DDR2 SDRAM。那么DDR SDRAM和SDRAM的区别在于DDR(double data rate)双倍速率。SDRAM只在时钟的上升沿表示一个数据,而DDR SDRAM能在上升沿和下降沿都表示一个数据。DDR也一步步经过改良出现了一代、二代、三代,现在也有四代,自然价格也是水涨船高。

非易失性存储器常见的有ROM,FLASH,光盘,软盘,机械硬盘。他们作用相同,只是实现工艺不一样。

光盘、软盘和机械硬盘都很好理解,不做解释。

ROM(Read Only Memory)在以前就是只读存储器,就是说这种存储器只能读取它里面的数据无法向里面写数据。实际是以前向存储器写数据不容易,所以这种存储器就是厂家造好了写入数据,后面不能再次修改。现在技术成熟了,ROM也可以写数据,但是名字保留了下来。

ROM分为MASK ROM、OTPROM、EPROM、EEPROM。MASK ROM是掩膜ROM这种ROM是一旦厂家生产出来,使用者无法再更改里面的数据。OTPROM(One Time Programable ROM)一次可变成存储器,出厂后用户只能写一次数据,然后再也不能修改了,一般做存储密钥。EPROM(Easerable Programable ROM)这种存储器就可以多次擦除然后多次写入了。但是要在特定环境紫外线下擦除,所以这种存储器也不方便写入。EEPROM(Eelectrically Easerable Programable ROM)电可擦除ROM,现在使用的比较多因为只要有电就可擦除数据,就可以写入数据。

FLASH是一种可以写入和读取的存储器,叫闪存,FLASH也叫FLASH ROM,有人把FLASH当做ROM。FLASH和EEPROM相比,FLASH的存储容量大。FLASH的速度比现在的机械硬盘速度快,现在的U盘和SSD固态硬盘都是Nandflash。FLASH又分为Norflash和Nandflash。

flash eeprom 的区别

阅读数 25

单片机样片申请

阅读数 513

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