nonocast / hello-zhulaoshi

朱有鹏单片机和嵌入式课程笔记
6 stars 0 forks source link

单片机实践 (Part 1) #2

Open nonocast opened 3 years ago

nonocast commented 3 years ago

1.6.1 LED灯

vscode需要做两个设置:

app.c

#include <8051.h>

void main() {
  P1_0 = 0;

  while(1) {}
}

8051.h中定义的了寄存器的变量

/*  BYTE Register  */
__sfr __at (0x80) P0   ;
__sfr __at (0x81) SP   ;
__sfr __at (0x82) DPL  ;
__sfr __at (0x83) DPH  ;
__sfr __at (0x87) PCON ;
__sfr __at (0x88) TCON ;
__sfr __at (0x89) TMOD ;
__sfr __at (0x8A) TL0  ;
__sfr __at (0x8B) TL1  ;
__sfr __at (0x8C) TH0  ;
__sfr __at (0x8D) TH1  ;
__sfr __at (0x90) P1   ;
__sfr __at (0x98) SCON ;
__sfr __at (0x99) SBUF ;
__sfr __at (0xA0) P2   ;
__sfr __at (0xA8) IE   ;
__sfr __at (0xB0) P3   ;
__sfr __at (0xB8) IP   ;
__sfr __at (0xD0) PSW  ;
__sfr __at (0xE0) ACC  ;
__sfr __at (0xF0) B    ;

/*  BIT Register  */
/* P0 */
__sbit __at (0x80) P0_0 ;
__sbit __at (0x81) P0_1 ;
__sbit __at (0x82) P0_2 ;
__sbit __at (0x83) P0_3 ;
__sbit __at (0x84) P0_4 ;
__sbit __at (0x85) P0_5 ;
__sbit __at (0x86) P0_6 ;
__sbit __at (0x87) P0_7 ;
...

跑马灯所需要的C语言基础:

#include <stdio.h>  /* printf */
#include <stdlib.h> /* strtol */
#include <string.h> /* strcat */

const char* getBitString(int x) {
  static char b[9];
  b[0] = '\0';

  int z;
  for (z = 128; z > 0; z >>= 1) {
    strcat(b, ((x & z) == z) ? "1" : "0");
  }

  return b;
}

int main() {
  printf("0x01:\t\t%s\n", getBitString(0x01));
  printf("!0x01:\t\t%s\n", getBitString(!0x01));
  printf("!0x00:\t\t%s\n", getBitString(!0x00));
  printf("~0x01:\t\t%s\n", getBitString(~0x01));
  printf("0x01<<1:\t%s\n", getBitString(0x01 << 1));
  printf("~(0x01<<1):\t%s\n", getBitString(~(0x01 << 1)));

  printf("0xfe:\t\t%s\n", getBitString(0xfe));
  printf("0xfe<<1:\t%s\n", getBitString(0xfe<<1));

  printf("---\n");

  int i = 0;
  int P0 = 0xff;
  for (i = 0; i < 8; ++i) {
    P0 = ~(0x01 << i);
    printf("P0: %s\n", getBitString(P0));
  }

  return 0;
}

输出:

0x01:           00000001
!0x01:          00000000
!0x00:          00000001
~0x01:          11111110
0x01<<1:        00000010
~(0x01<<1):     11111101
0xfe:           11111110
0xfe<<1:        11111100
---
P0: 11111110
P0: 11111101
P0: 11111011
P0: 11110111
P0: 11101111
P0: 11011111
P0: 10111111
P0: 01111111

1.7 数码管

1.8 LED点阵

74HC595

app.c: 点亮16x16所有LED

#include <8051.h>
#include <stdbool.h>

typedef unsigned int u16;
typedef unsigned char u8;

#define SER P3_4  // serial
#define RCK P3_5  // storage register clock
#define SCK P3_6  // shift clock
#define _nop_() __asm NOP __endasm

void delay(u16 i) {
  while (i--)
    ;
}

void main() {
  u8 i = 0;

  // POS[0-15] = 0
  for (i = 0; i < 16; ++i) {
    SER = 0;
    SCK = 0;
    SCK = 1;
  }

  // NEG[0-15] = 1
  for (i = 0; i < 16; ++i) {
    SER = 1;
    SCK = 0;
    SCK = 1;
  }

  RCK = 0;
  RCK = 1;

  while (true) {
  }
}

random led:

void main() {
  u8 i = 0;

  while (true) {
    for (i = 0; i < 32; ++i) {
      SER = rand() % 2;
      SCK = 0;
      SCK = 1;
    }

    RCK = 0;
    RCK = 1;
  }
}

1.9 按键处理

app.c: 将按键和LED关联起来

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned int u16;
typedef unsigned char u8;

#define BUTTON1 P1_0
#define LED1 P0_0

void delay(u16 i);
void init();
void loop();

void main() {
  init();
  while (true) {
    loop();
  }
}

void init() {
  LED1 = 1;
}

void loop() {
  LED1 = BUTTON1;
}

中断

void main() {
  init();
  while (true) {
    loop();
  }
}

void init() {}

void loop() {
  u8 i = 0;
  for (i = 0; i < 16; ++i) {
    P0 = ~segments[i];
    delay(20000);
  }

  P2 = P1;
}

简而言之,就是P3.2引脚给出一个下降沿,比如按键触发,就会调用程序中的interrupt, 最简单就是将P3.2连接到GND就可以直接给出一个下降沿触发中断。

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned int u16;
typedef unsigned char u8;

u8 status;
void delay(u16 i);
void init();
void loop();

void main() {
  init();
  while (true) {
    // loop();
  }
}

void init() {
  IT0 = 1;  // set INT0 interrupt type: (1: falling, 0: low level)
  EX0 = 1;  // enable INT0 interrupt
  EA = 1;   // open global interrupt switch
  P2_1 = 1;
}

void int0() __interrupt(0) {
  delay(1000);
  P2_1 = !P2_1;
}

void loop() {}

void delay(u16 i) {
  while (i--)
    ;
}

1.10 定时器和计数器

app.c

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned int word;
typedef unsigned char byte;

void init();
void loop();

void main() {
  init();
  while (true) {
    loop();
  }
}

word count = 0;

void init() {
  // 设置模式: 16位计时器
  TMOD = 0x01;
  // 设置时钟周期: 1ms (1ms/1us=1000次, 如果需要溢出触发则65536-1000=0xfc18)
  TH0 = 0xfc;
  TL0 = 0x18;
  TR0 = 1;
  ET0 = 1;
  EA = 1;

  count = 1000;
}

void timer0() __interrupt(1) {
  TH0 = 0xfc;
  TL0 = 0x18;

  if (--count == 0) {
    P0_0 = !P0_0;
    count = 1000;
  }
}

void loop() {}

1.11 蜂鸣器

1.12 电机

直流电机

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned int word;
typedef unsigned char byte;

void delay(word i);
void init();
void loop();

void main() {
  init();
  while (true) {
    loop();
  }
}

void init() {
  IT0 = 1; // set INT0 interrupt type: (1: falling, 0: low level)
  EX0 = 1; // enable INT0 interrupt
  EA = 1;  // open global interrupt switch
  P1_2 = 0;
}

void loop() {}

void int0() __interrupt(0) {
  delay(1000);
  if (P3_2 == 0) {
    P1_2 = !P1_2;
  }
}

void delay(word i) {
  while (i--)
    ;
}

步进电机

1.13 串口通信

app.c 发送hello world

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned int word;
typedef unsigned char byte;

void delay(word i);
void init();
void loop();
void sendByte(byte);
void sendString(char *string);

void main() {
  init();
  while (true) {
    loop();
  }
}

void init() {
  SCON = 0x50; // 0b 0101 0000
  TMOD = 0x20; // set timer1 as 8-bit auto reload mode
  PCON = 0x80;
  TH1 = TL1 = 0xf3;

  TR1 = 1; // timer1 start run
  ES = 1;  // enable uart interrupt
  EA = 1;  // open master inerrupt switch
}

void loop() {
  sendString("hello world\n");
  P0_0 = !P0_0;
  delay(50000);
}

void sendByte(byte data) {
  SBUF = data;
  while (!TI)
    ;
  TI = 0;
}

void sendString(char *string) {
  while (*string) {
    sendByte(*string++);
  }
}

void delay(word i) {
  while (i--)
    ;
}

RS485