蓝桥杯CT107D 单片机编程例题
时间:2023-05-17 01:07:00
一、按键
#include "stc15f2k60s2.h" #define InitHC138(n) { P2 = P2 & 0x1f | (n << 5);} #define u8 unsigned char #define u32 unsigned int bit key_flag; // 按键标志位 u8 key; // 按键状态 u8 Key4_Read(void) ///独立按钮扫描函数,读取键值 { u32 Key_temp; u8 Key_Value; P3 |= 0x0f; Key_temp = P3&0x0f; switch(Key_temp) { case 0x0e : Key_Value = 7; break; //S7 case 0x0d : Key_Value = 6; break; //S6 case 0x0b : Key_Value = 5; break; //S5 case 0x07 : Key_Value = 4; break; //S4 default: Key_Value = 0; } return Key_Value; } u8 Key16_Read(void) //
矩阵按键扫描函数,读取键值 { u32 Key_temp; u8 Key_Value; //按键扫描的识别部分 P44=0; P42=1; P35=1; P34=1; P3|=0X0F; //第一列拉低,其余全为高 Key_temp = P3; //读取P3低四位I/O状态 P44=1; P42=0; P35=1; P34=1; P3|=0X0F; //第二列拉低,其余全为高 Key_temp = (Key_temp<<4) | (P3&0X0F); //读取P3低四位I/O状态 P44=1; P42=1; P35=0; P34=1; P3|=0X0F; //第三列拉低,其余全为高 Key_temp = (Key_temp<<4) | (P3&0X0F); //读取P3低四位I/O状态 P44=1; P42=1; P35=1; P34=0; P3|=0X0F; //第四列拉低,其余全为高 Key_temp = (Key_temp<<4) | (P3&0X0F); //读取P3低四位I/O状态 //有按键按下Key_temp相应位为0 //按键扫描的编码部分 switch(~Key_temp) { case 0X8000: Key_Value = 4; break; //S4 case 0X4000: Key_Value = 5; break; //S5 case 0X2000: Key_Value = 6; break; //S6 case 0X1000: Key_Value = 7; break; //S7 case 0X0800: Key_Value = 8; break; //S8 case 0X0400: Key_Value = 9; break; //S9 case 0X0200: Key_Value = 10; break; //S10 case 0X0100: Key_Value = 11; break; //S11 case 0X0080: Key_Value = 12; break; //S12 case 0X0040: Key_Value = 13; break; //S13 case 0X0020: Key_Value = 14; break; //S14 case 0X0010: Key_Value = 15; break; //S15 case 0X0008: Key_Value = 16; break; //S16 case 0X0004: Key_Value = 17; break; //S17 case 0X0002: Key_Value = 18; break; //S18 case 0X0001: Key_Value = 19; break; //S19 default: Key_Value = 0; //无按键按下 } return Key_Value; } void Key_config() { while(key_flag) { key_flag = 0; key = Key4_Read(); switch(key) { case 7: InitHC138(4); P0 = 0xfe; P2 = 0x00; break; case 6: InitHC138(4); P0 = 0xff; P2 = 0x00; break; } } } void Timer1Init(void) //1毫秒@12.000MHz { AUXR &= 0xBF; //定时器时钟12T模式 TMOD &= 0x0F; //设置定时器模式 TH1 = (65535 - 1000) / 256; //设置定时初始值 TL1 = (65535 - 1000) % 256; //设置定时初始值 TF1 = 0; //清除TF1标志 TR1 = 1; //定时器1开始计时 ET1 = 1; EA = 1; } void main() { InitHC138(4); P0 = 0xff; P2 = 0x00; InitHC138(5); P0 = 0x00; P2 = 0x00; Timer1Init(); while(1) { Key_config(); } } void Serv_T1() interrupt 3 { u32 i; TH1 = (65535 - 1000) / 256; //设置定时初始值 TL1 = (65535 - 1000) % 256; //设置定时初始值 i++; if(i == 10) { i = 0; key_flag = 1; } }
二、外部中断
#include "stc15f2k60s2.h"
#define InitHC138(n) {
P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S4 = P3^3;
void Delay_ms(unsigned int t)
{
unsigned char i, j;
while(t--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void Init_key()
{
if(!S7)
{
Delay_ms(15);
if(!S7)
{
S4 = 0;
}
while(!S7);
}
if(!S6)
{
Delay_ms(15);
if(!S6)
{
S4 = 1;
}
while(!S6);
}
}
void Init_inter0()
{
IT1 = 0; // 低电平触发,触发之后必须是高电平变为低电平才会触发
// IT1 = 1; // 跳变沿触发
EX1 = 1; // 打开 INT0 的中断允许
EA = 1; // 打开总中断
}
void Servive_0() interrupt 2 // 外部中断1
{
InitHC138(4);
led1 = ~led1;
}
void main (void)
{
InitHC138(5);
P0 = 0x00; P2 = 0x00;
InitHC138(4);
P0 = 0xff; P2 = 0x00;
Init_inter0();
while (1)
{
Init_key();
}
}
三、 定时器
#include "stc15f2k60s2.h"
#define InitHC138(n) {
P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S4 = P3^3;
void Init_Timer_0()
{
TMOD |= 0x01; // 选择定时器0,工作方式1,仅用TR0打开启动
TH0 = (65536 - 1000) / 256; // 定时1ms
TL0 = (65536 - 1000) % 256;
ET0 = 1; // 打开定时器0中断允许
EA = 1; // 打开总中断
TR0 = 1; // 打开定时器
}
unsigned int count = 0;
void Timer0() interrupt 1
{
count++;
if(count == 500) // count == 500 既是经过500ms
{
count = 0;
InitHC138(4);
led1 = ~led1;
P2 = 0x00;
}
// 一定要记得重载
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
}
void main (void)
{
InitHC138(5);
P0 = 0x00; P2 = 0x00;
InitHC138(4);
P0 = 0xff; P2 = 0x00;
Init_Timer_0();
while (1)
{
// CPU不参与定时器的运行
}
}
定时器2实现数码刷新
// ds1302实现电子钟
#include "STC15F2K60S2.h"
#include "ds1302.h"
#define InitHC138(n) {
P2 = P2 & 0x1f | (n << 5);}
#define u8 unsigned char
#define u32 unsigned int
// 段码
code u8 tab[]={
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf};
u8 Buf[8]; // 数码管的显示缓冲区
u8 Timer[7] = {
0x24,0x59,0x23,0x03,0x03,0x03,0x20};
void DS1302_config()
{
u8 i;
u8 Write = 0x80;
Write_Ds1302_Byte(0x8e, 0x00); // 关闭保护,可以写入
for(i = 0; i < 7; i++)
{
Write_Ds1302_Byte(Write, Timer[i]);
Write += 2;
}
Write_Ds1302_Byte(0x8e, 0x80); // 恢复保护,拒绝写入
}
void Read_ds1320_time()
{
u8 i;
u8 Read = 0x81;
for(i = 0; i < 7; i++)
{
Timer[i] = Read_Ds1302_Byte(Read);
Read += 2;
}
}
// 数码管显示端口配置
void Display_SMG(u8 pos, u8 dat)
{
InitHC138(7);
P0 = 0xff; P2 = 0x00;
InitHC138(6);
P0 = 0x01 << pos; P2 = 0x00;
InitHC138(7);
P0 = dat; P2 = 0x00;
}
// 定时器2配置 1ms
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0x18; //设置定时初始值
T2H = 0xFC; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; // 使能中断
EA = 1;
}
// 定时器2中断
void T0_Servive() interrupt 12
{
u8 pos;
T2L = 0x18; //设置定时初始值
T2H = 0xFC; //设置定时初始值
Display_SMG(pos, Buf[pos]); // 1ms刷新一个数码管,即每隔8ms刷新一次
if(++pos == 8) pos = 0; // 通过移位来实现动态显示
}
// 数码管显示数据的配置函数
void smgdatset(u8 d0,u8 d1,u8 d2,u8 d3,
u8 d4,u8 d5,u8 d6,u8 d7)
{
Buf[0]=d0;
Buf[1]=d1;
Buf[2]=d2;
Buf[3]=d3;
Buf[4]=d4;
Buf[5]=d5;
Buf[6]=d6;
Buf[7]=d7;
}
void Show_time()
{
Read_ds1320_time();
// 显示时间
smgdatset(tab[Timer[2]/16], tab[Timer[2]%16], tab[11],
tab[Timer[1]/16], tab[Timer[1]%16], tab[11],
tab[Timer[0]/16], tab[Timer[0]%16]);
}
int main(void)
{
InitHC138(4);
P0 = 0xff; P2 = 0x00;
InitHC138(5);
P0 = 0x00; P2 = 0x00;
Timer2Init();
DS1302_config();
while(1)
{
Show_time();
}
}
四、串口通讯
#include "stc15f2k60s2.h"
#define InitHC138(n) {
P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
void UartInit(void) //115200bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE8; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
void uart() interrupt 4 //串口通信中断服务函数
{
if(RI)
{
RI=0;
}
if(TI)
{
TI=0;
}
}
void uart_sendchar(unsigned char ch) // 发送字符函数
{
<