开发板
本人开发板:普中科技
C语言问题
1、使用 _nop_(); 需要写头文件 #include "intrins.h"
2、! 取反符号
项目实验
都是基础简单实现对应功能。
LED灯的闪烁
电路连接情况
JP12 与 JP10 导线连接;LE 与 VCC跳线帽连接。
代码
#include <STC89C5xRC.H>
sbit D11 = P0^0;
sbit D12 = P0^1;
sbit D13 = P0^2;
sbit D14 = P0^3;
sbit D15 = P0^4;
sbit D16 = P0^5;
sbit D17 = P0^6;
sbit D18 = P0^7;
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 13;
j = 156;
k = 83;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
int main()
{
P0=0X00;
while(1)
{
D11=1; D12=0; D13=1; D14=0;
D15=1; D16=0; D17=1; D18=0;
Delay300ms();
D11=0; D12=1; D13=0; D14=1;
D15=0; D16=1; D17=0; D18=1;
Delay300ms();
}
}
结果
LED灯交替闪烁。
独立按键
电路连接情况
JP5与JP11 导线连接。
代码
#include <STC89C5xRC.H>
#include "intrins.h"
sbit D11 = P0^0;
sbit D12 = P0^1;
sbit D13 = P0^2;
sbit D14 = P0^3;
sbit D15 = P0^4;
sbit D16 = P0^5;
sbit D17 = P0^6;
sbit D18 = P0^7;
sbit K1 = P2^0;
sbit K2 = P2^1;
sbit K3 = P2^2;
sbit K4 = P2^3;
sbit K5 = P2^4;
sbit K6 = P2^5;
sbit K7 = P2^6;
sbit K8 = P2^7;
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 54;
j = 198;
do
{
while (--j);
} while (--i);
}
void Key_scan()
{
if(K1==0)
{
Delay5ms();
if(K1==0)
{
D11=1;
while(K1==0);
}
}
else if(K2==0)
{
Delay5ms();
if(K2==0)
{
D12=1;
while(K2==0);
}
}
else if(K3==0)
{
Delay5ms();
if(K3==0)
{
D13=1;
while(K3==0);
}
}
else if(K4==0)
{
Delay5ms();
if(K4==0)
{
D14=1;
while(K4==0);
}
}
else if(K5==0)
{
Delay5ms();
if(K5==0)
{
D15=1;
while(K5==0);
}
}
else if(K6==0)
{
Delay5ms();
if(K6==0)
{
D16=1;
while(K6==0);
}
}
else if(K7==0)
{
Delay5ms();
if(K7==0)
{
D17=!D17;
while(K7==0);
}
}
else if(K8==0)
{
Delay5ms();
if(K8==0)
{
D18=!D18;
while(K8==0);
}
}
}
int main()
{
P0=0X00;
while(1)
{
Key_scan();
}
}
结果
按键K1-K6,按下开启D11 - D16; K7、K8按下D17、D18取反,为亮或灭;
按键点亮数码管
电路连接情况
静态共阳数码管 JP3与P1导线连接;按键为K1;
代码
#include <STC89C5xRC.H>
#include "intrins.h"
#define SMG_display P1
sbit K1 = P2^0;
unsigned char code SMG_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //共阳编码 高电平熄灭
0xff,0xc1,0x8c,0xc8}; // off U P n
//unsigned char code SMG_code[18] = { // 共阴编码 (高电平点亮)
// 0x3f, 0x06, 0x5b, 0x4f , 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,
// 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,0xff, 0x00};
unsigned char count;
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 54;
j = 198;
do
{
while (--j);
} while (--i);
}
void Key_scan()
{
if(K1==0)
{
Delay5ms();
if(K1==0)
{
D11=1;
SMG_display=SMG_code[count++];
if(count>=14)
count=0;
while(K1==0);
}
}
}
int main()
{
SMG_display=SMG_code[0];
while(1)
{
Key_scan();
}
}
结果
多次按下K1,数码管显示依次为 0到9,“全灭,P,U,n ”。
动态数码管显示
电路连接情况
数码管为共阴。
J12与PI 导线连接;J21中LE与VCC连接;J16与J15连接;
J6中3(A)接P22; 2(B)接P23; 1(C)接P24;
代码
#include <STC89C5xRC.H>
#include "intrins.h"
#define SMG_display P1
sbit LSA = P2^2; // 控制位选的IO
sbit LSB = P2^3;
sbit LSC = P2^4;
// 显示内容
//unsigned char code SMG_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //
// 0xff,0xc1,0x8c,0xc8}; // off U P n
// 显示缓存
unsigned char code SMG_buff[8]={0,1,2,3,4,5,6,7};
unsigned char code SMG_code[18] = { // 共阴编码 (高电平熄灭、低电平点亮)
0x3f, 0x06, 0x5b, 0x4f , 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,
0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,0xff, 0x00};
void Display()
{
unsigned char i;
unsigned int j;
for (i = 0; i < 8; i++)
{
switch (i)
{
case 0: LSA=0; LSB=0; LSC=0; break; // 选择第1个数码管
case 1: LSA=1; LSB=0; LSC=0; break; // 选择第2个数码管
case 2: LSA=0; LSB=1; LSC=0; break; // 选择第3个数码管
case 3: LSA=1; LSB=1; LSC=0; break; // 选择第4个数码管
case 4: LSA=0; LSB=0; LSC=1; break; // 选择第5个数码管
case 5: LSA=1; LSB=0; LSC=1; break; // 选择第6个数码管
case 6: LSA=0; LSB=1; LSC=1; break; // 选择第5个数码管
case 7: LSA=1; LSB=1; LSC=1; break; // 选择第6个数码管
}
SMG_display = SMG_code[SMG_buff[i]]; // 显示对应数码管的值
j = 200; // 延长数码管显示的持续时间
while (j--);
SMG_display = 0x00; // 关闭当前数码管,为下一个数码管显示做准备
}
}
int main()
{
while(1)
{
Display();
}
}
结果:
八个数码管依次显示:0 到 7;
矩阵按键
电路连接情况
JP4接P0引脚;
代码
#include <STC89C5xRC.H>
#include "intrins.h"
#define SMG_display P1
#define KEY_in P0
sbit LSA = P2^2; // 控制位选的IO
sbit LSB = P2^3;
sbit LSC = P2^4;
unsigned char SMG_buff[8]={17,17,17,17,17,17,17,17};
unsigned char code SMG_code[18] = { // 共阴编码 (高电平熄灭、低电平点亮)
0x3f, 0x06, 0x5b, 0x4f , 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, //0-9
0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,0xff, 0x00}; //
unsigned char KeyValue;
void Display()
{
unsigned char i;
unsigned int j;
for (i = 0; i < 8; i++)
{
switch (i)
{
case 0: LSA=0; LSB=0; LSC=0; break; // 选择第1个数码管
case 1: LSA=1; LSB=0; LSC=0; break; // 选择第2个数码管
case 2: LSA=0; LSB=1; LSC=0; break; // 选择第3个数码管
case 3: LSA=1; LSB=1; LSC=0; break; // 选择第4个数码管
case 4: LSA=0; LSB=0; LSC=1; break; // 选择第5个数码管
case 5: LSA=1; LSB=0; LSC=1; break; // 选择第6个数码管
case 6: LSA=0; LSB=1; LSC=1; break; // 选择第5个数码管
case 7: LSA=1; LSB=1; LSC=1; break; // 选择第6个数码管
}
SMG_display = SMG_code[SMG_buff[i]]; // 显示对应数码管的值
j = 200; // 延长数码管显示的持续时间
while (j--);
SMG_display = 0x00; // 关闭当前数码管,为下一个数码管显示做准备
}
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 54;
j = 198;
do
{
while (--j);
} while (--i);
}
void Key_scan() // 取键值函数
{
unsigned char keyState = KEY_in;
unsigned char X, Y, Z;
KeyValue = 0xFF; // 初始化KeyValue为0xFF,即无键按下的状态
KEY_in = 0x0f; // 先对P1置数进行行扫描
if (KEY_in != 0x0f) // 判断是否有键按下
{
Delay5ms(); // 延时,软件去干扰
if (KEY_in != 0x0f) // 确认按键按下
{
X = KEY_in; // 保存行扫描时有键按下时状态
KEY_in = 0xf0; // 列扫描
Y = KEY_in; // 保存列扫描时有键按下时状态
Z = X | Y; // 取出键值
// 根据取出的键值判断是哪一个键被按下
switch (Z)
{
case 0xee: KeyValue = 1; break;
case 0xde: KeyValue = 2; break;
case 0xbe: KeyValue = 3; break;
case 0x7e: KeyValue = 4; break;
case 0xed: KeyValue = 5; break;
case 0xdd: KeyValue = 6; break;
case 0xbd: KeyValue = 7; break;
case 0x7d: KeyValue = 8; break;
case 0xeb: KeyValue = 9; break;
case 0xdb: KeyValue = 10; break;
case 0xbb: KeyValue = 11; break;
case 0x7b: KeyValue = 12; break;
case 0xe7: KeyValue = 13; break;
case 0xd7: KeyValue = 14; break;
case 0xb7: KeyValue = 15; break;
case 0x77: KeyValue = 16; break;
}
SMG_buff[0]=KeyValue;
}
}
}
int main()
{
while(1)
{
Key_scan();
Display();
}
}
结果:
矩阵按键依次按下:数码管依次显示为:1-9,a-f, 全亮
蜂鸣器继电器
电路连接情况
蜂鸣器接P21;继电器接P20;
代码
#include <STC89C5xRC.H>
#include "intrins.h"
#define KEY_in P0
sbit Relay = P2^0;
sbit Buzzer = P2^1;
unsigned char KeyValue;
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 54;
j = 198;
do
{
while (--j);
} while (--i);
}
void Key_scan() // 取键值函数
{
unsigned char keyState = KEY_in;
unsigned char X, Y, Z;
KeyValue = 0xFF; // 初始化KeyValue为0xFF,即无键按下的状态
KEY_in = 0x0f; // 先对P1置数进行行扫描
if (KEY_in != 0x0f) // 判断是否有键按下
{
Delay5ms(); // 延时,软件去干扰
if (KEY_in != 0x0f) // 确认按键按下
{
X = KEY_in; // 保存行扫描时有键按下时状态
KEY_in = 0xf0; // 列扫描
Y = KEY_in; // 保存列扫描时有键按下时状态
Z = X | Y; // 取出键值
// 根据取出的键值判断是哪一个键被按下
switch (Z)
{
case 0xee: KeyValue = 1; break;
case 0xde: KeyValue = 2; break;
case 0xbe: KeyValue = 3; break;
case 0x7e: KeyValue = 4; break;
case 0xed: KeyValue = 5; break;
case 0xdd: KeyValue = 6; break;
case 0xbd: KeyValue = 7; break;
case 0x7d: KeyValue = 8; break;
case 0xeb: KeyValue = 9; break;
case 0xdb: KeyValue = 10; break;
case 0xbb: KeyValue = 11; break;
case 0x7b: KeyValue = 12; break;
case 0xe7: KeyValue = 13; break;
case 0xd7: KeyValue = 14; break;
case 0xb7: KeyValue = 15; break;
case 0x77: KeyValue = 16; break;
}
if(KeyValue==1)
Relay=!Relay;
else if(KeyValue==2)
Buzzer=!Buzzer;
}
}
}
int main()
{
while(1)
{
Key_scan();
}
}
结果:
按下S1按键,继电器工作;按下S2按键,蜂鸣器工作;
定时器0的使用
电路连接情况
J12与P1导线相连;
代码
#include <STC89C5xRC.H>
sbit D11 = P1^0;
sbit D13 = P1^2;
sbit D15 = P1^4;
unsigned int count_led1;
unsigned int count_led3;
unsigned int count_led5;
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
int main()
{
Timer0Init();
P1=0X00;
while(1)
{
}
}
void timer0() interrupt 1
{
count_led1++;
count_led3++;
count_led5++;
if(count_led1==100)
{
D11=!D11;
count_led1=0;
}
if(count_led3==200)
{
D13=!D13;
count_led3=0;
}
if(count_led5==400)
{
D15=!D15;
count_led5=0;
}
}
结果
定时器每1ms执行一次;
count_led1加到100,LED1电平取反;count_led3加到200,LED3电平取反;.......。。。。
定时器1的使用
电路连接情况
同定时器0相同,连接led灯;
代码
#include <STC89C5xRC.H>
sbit D11 = P1^0;
sbit D13 = P1^2;
sbit D15 = P1^4;
sbit D17 = P1^6;
sbit D18 = P1^7;
unsigned int count_led1;
unsigned int count_led3;
unsigned int count_led5;
unsigned int count_led7,count_led8;
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void Timer1Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x9A; //设置定时初值
TH1 = 0xA9; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
}
int main()
{
Timer0Init();
Timer1Init();
P1=0X00;
while(1)
{
}
}
void timer0() interrupt 1
{
count_led1++;
count_led3++;
count_led5++;
if(count_led1==200)
{
D11=!D11;
count_led1=0;
}
if(count_led3==400)
{
D13=!D13;
count_led3=0;
}
if(count_led5==800)
{
D15=!D15;
count_led5=0;
}
}
void timer1() interrupt 3
{
count_led7++;
count_led8++;
if(count_led7==100)
{
D17=!D17;
count_led7=0;
}
if(count_led8==200)
{
D18=!D18;
count_led8=0;
}
}
结果:
LED闪烁。
中断0的使用
电路连接情况
数码管动态显示连接P1;中断功能INT0引脚P23接K1(JP5的8);
代码
#include <STC89C5xRC.H>
#include "intrins.h"
#define SMG_display P1
#define KEY_in P0
sbit LSA = P2^2; // 控制位选的IO
sbit LSB = P2^3;
sbit LSC = P2^4;
unsigned char SMG_buff[8]={17,17,17,17,17,17,17,17};
unsigned char code SMG_code[18] = { // 共阴编码 (高电平熄灭、低电平点亮)
0x3f, 0x06, 0x5b, 0x4f , 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, //0-9
0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,0xff, 0x00}; //
unsigned char count;
void Display()
{
unsigned char i;
unsigned int j;
for (i = 0; i < 8; i++)
{
switch (i)
{
case 0: LSA=0; LSB=0; LSC=0; break; // 选择第1个数码管
case 1: LSA=1; LSB=0; LSC=0; break; // 选择第2个数码管
case 2: LSA=0; LSB=1; LSC=0; break; // 选择第3个数码管
case 3: LSA=1; LSB=1; LSC=0; break; // 选择第4个数码管
case 4: LSA=0; LSB=0; LSC=1; break; // 选择第5个数码管
case 5: LSA=1; LSB=0; LSC=1; break; // 选择第6个数码管
case 6: LSA=0; LSB=1; LSC=1; break; // 选择第5个数码管
case 7: LSA=1; LSB=1; LSC=1; break; // 选择第6个数码管
}
SMG_display = SMG_code[SMG_buff[i]]; // 显示对应数码管的值
j = 200; // 延长数码管显示的持续时间
while (j--);
SMG_display = 0x00; // 关闭当前数码管,为下一个数码管显示做准备
}
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 54;
j = 198;
do
{
while (--j);
} while (--i);
}
void INT0_Init(void)
{
IT0 = 1; //设置下降沿触发中断
EX0 = 1; //使能外部中断0
EA = 1; //使能全局中断
}
int main()
{
INT0_Init();
while(1)
{
SMG_buff[0] = count/100;
SMG_buff[1] = count%100/10;
SMG_buff[2] = count%10;
Display();
}
}
void ExInt0() interrupt 0
{
if(P32 == 0)
{
Delay5ms();
if(P32 == 0)
{
count++;
}
}
}
结果
K1按下,数码管显示的数值为检测到中断0成功识别到连续两次,P32引脚电平被拉低的次数。
8*8点阵
电路连接情况
74HC595移位数据:P595 A连接J12:用于控制位选。控制DPa,DPb......电平。
P0引脚接 J19 (绿色灯)或 J20 (红色灯)用于控制段选。显示一行(列)的八个灯亮灭。
代码
#include <STC12C5A60S2.H>
sbit LSA = P2^2; // 控制位选的IO
sbit LSB = P2^3;
sbit LSC = P2^4;
sbit SER=P3^4;
sbit RCK=P3^5;
sbit SRCLK=P3^6;
unsigned char LED[]={0x00,0x18,0x3C,0x1E,0x0F,0x1E,0x3C,0x18};
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
void MatrixLED_Init(void)
{
RCK=0;
SRCLK=0;
}
void MatrixLED_Show(unsigned char Column,unsigned char Date)
{
unsigned char i;
for(i=0;i<8;i++)
{
SER=Date&(0x80>>i);
SRCLK=1;
SRCLK=0;
}
RCK=1;
RCK=0;
P0=~(0x80>>Column);
Delay1ms();
}
void Display()
{
unsigned char i;
unsigned int j;
for (i = 0; i < 8; i++)
{
switch (i)
{
case 0: LSA=0; LSB=0; LSC=0; break; // 选择第1个数码管
case 1: LSA=1; LSB=0; LSC=0; break; // 选择第2个数码管
case 2: LSA=0; LSB=1; LSC=0; break; // 选择第3个数码管
case 3: LSA=1; LSB=1; LSC=0; break; // 选择第4个数码管
case 4: LSA=0; LSB=0; LSC=1; break; // 选择第5个数码管
case 5: LSA=1; LSB=0; LSC=1; break; // 选择第6个数码管
case 6: LSA=0; LSB=1; LSC=1; break; // 选择第5个数码管
case 7: LSA=1; LSB=1; LSC=1; break; // 选择第6个数码管
}
MatrixLED_Show(i,LED[i]);
j = 100; // 延长数码管显示的持续时间
while (j--);
P0=0xFF;
}
}
void main()
{
MatrixLED_Init();
while(1)
{
Display();
}
}
结果
显示内容位心形图案。
结语
以上代码为89C52环境创建的项目代码,但本人开发板单片机型号为STC12C5A60S2,
测试过程中发现延时、定时器设定的理论时间 与 实物显示时间长短反应不一致。但可运行。
故基础部分再次结束。
我将再下一篇用STC12C5A60S2单片机芯片。
继续书写优化代码。