模板如下
一、可以实现一秒钟点一次灯,只需要修改led_buf
unsigned char led_buf = 0x00;
void led_output() //点灯
{
P0 = ~led_buf;
P2 |= 0x80;
P2 &= ~0xE0;
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初值
TH1 = 0xD1; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
unsigned int timer1s = 0;
void Timer1Isr() interrupt 3
{
led_output();
timer1s++;
}
void main()
{
Timer1Init();
while(1)
{
if(timer1s >= 1000)
{
timer1s = 0;
led_buf ^= 0x40;
}
}
}
二、数码管
/************* 本地常量声明 **************/
unsigned char code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
unsigned char code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
unsigned char dig_buf[8] = {16,16,16,16,16,16,16,16};
void dig_output()
{
static unsigned char dig_com = 0;
P0 = 0x00; //消隐
P2 |= 0xc0;
P2 &= ~0xE0;
P0 = ~t_display[dig_buf[dig_com]]; //段选
P2 |= 0xe0;
P2 &= ~0xE0;
P0 = T_COM[dig_com]; //位选
P2 |= 0xc0;
P2 &= ~0xE0;
if(++dig_com >= 8)
{
dig_com = 0;
}
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初值
TH1 = 0xD1; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
unsigned int timer1s = 0;
void Timer1Isr() interrupt 3
{
led_output();
dig_output();
timer1s++;
}
三、按键
需要把按键放在定时器里,每10ms执行一次,进行消抖处理,
独立按键:
unsigned char key_value =0;
unsigned char key_state = 0;
void key_scan()
{
P3 |= 0x0F;
if(~P3 & 0X0F)
{
if(key_state < 255)
key_state++;
if(P33 == 0)
key_value = 4;
if(P32 == 0)
key_value = 5;
if(P31 == 0)
key_value = 6;
if(P30 == 0)
key_value = 7;
}
else
{
key_value =0;
key_state = 0;
}
}
if(timer10ms >= 10)
{
timer10ms = 0;
key_scan();
if(key_value == 4 && key_state == 2)
{
cnt++;
}
else if(key_value == 5 && key_state == 2)
{
cnt--;
}
else if(key_value == 7 && key_state == 100)
{
if(++mode >= 4)
{
mode = 0;
}
}
else if(key_value == 6)
{
hold =1;
}
else
{
hold = 0;
}
dig_buf[0] = mode;
dig_buf[2] = hold;
dig_buf[5] = cnt / 100;
dig_buf[6] = cnt / 10 % 10;
dig_buf[7] = cnt % 10;
}
矩阵按键:
/* 矩阵按键 *///start
unsigned char code key_values[4][4]=
{
4,8,12,16,
5,9,13,17,
6,10,14,18,
7,11,15,19,
};
void key_scan_pad()
{
unsigned char H,L;
P3 = 0x0F;
P4 = 0x00;
if(~P3 & 0X0F)
{
if(key_state < 255)
key_state++;
if(P33 == 0) //行判断
H = 0;
if(P32 == 0)
H = 1;
if(P31 == 0)
H = 2;
if(P30 == 0)
H = 3;
P3 = 0xF0;
P4 = 0xFF;
if(P44 == 0) //列判断
L = 0;
if(P42 == 0)
L = 1;
if(P35 == 0)
L = 2;
if(P34 == 0)
L = 3;
key_value = key_values[H][L];
}
else
{
key_value =0;
key_state = 0;
}
}
/* 矩阵按键 *///end
void main()
{
unsigned char cnt = 50;
unsigned char mode = 0;
unsigned char hold = 0;
Timer1Init();
while(1)
{
if(timer1s >= 1000)
{
timer1s = 0;
led_buf ^= 0x40;
}
if(timer10ms >= 10)
{
timer10ms = 0;
//key_scan();
key_scan_pad();
if(key_value == 10 && key_state == 2)
{
cnt++;
}
else if(key_value == 5 && key_state == 2)
{
cnt--;
}
else if(key_value == 11 && key_state == 100)
{
if(++mode >= 4)
{
mode = 0;
}
}
else if(key_value == 16)
{
hold =1;
}
else
{
hold = 0;
}
dig_buf[0] = mode;
dig_buf[2] = hold;
dig_buf[5] = cnt / 100;
dig_buf[6] = cnt / 10 % 10;
dig_buf[7] = cnt % 10;
}
}
}
四、各种外设模块
1、DS1302模块
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "ds1302.h"
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
unsigned char ds1302_buf[]={0x23,0x59,0x55};
void write_ds1302()
{
Write_Ds1302_Byte(0x84,ds1302_buf[0]);
Write_Ds1302_Byte(0x82,ds1302_buf[1]);
Write_Ds1302_Byte(0x80,ds1302_buf[2]);
}
void read_ds1302()
{
ds1302_buf[0] = Read_Ds1302_Byte(0x85);
ds1302_buf[1] = Read_Ds1302_Byte(0x83);
ds1302_buf[2] = Read_Ds1302_Byte(0x81);
}
2、IIC AT24C02
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
sbit sda =P2^1;
sbit scl =P2^0;
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
// 自己编写
void write_at24c02(unsigned char addr, unsigned char dat)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
unsigned char read_at24c02(unsigned char addr)
{
unsigned char buf;
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
buf = I2CReceiveByte();
I2CSendByte(1);
I2CStop();
return buf;
}
void main()
{
unsigned char at24c02 = 0;
Timer1Init();
write_at24c02(0x80,127);
while(1)
{
if(timer10ms >= 10)
{
timer10ms = 0;
/* 按键区域 *///start
//key_scan();
key_scan_pad();
at24c02 = read_at24c02(0x80);
dig_buf[2][5] = at24c02 / 100;
dig_buf[2][6] = at24c02 / 10 % 10;
dig_buf[2][7] = at24c02 % 10;
}
}
}
3、PCF8591
#include "iic.h"
sbit sda =P2^1;
sbit scl =P2^0;
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
//自己写 iic
void write_at24c02(unsigned char addr, unsigned char Ddat)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(Ddat);
I2CWaitAck();
I2CStop();
}
unsigned char read_at24c02(unsigned char addr)
{
unsigned char buf;
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
buf = I2CReceiveByte();
I2CSendByte(1);
I2CStop();
return buf;
}
//PCF8591
unsigned char read_pcf8591(unsigned char channle)
{
unsigned char buf;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(channle);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
I2CReceiveByte();
I2CSendAck(0);
buf = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return buf;
}
#include <STC15F2K60S2.H>
#include "hardwork.h"
#include "ds1302.h"
#include "iic.h"
void main()
{
unsigned char temp = 0;
Timer1Init();
while(1)
{
if(timer1s >= 1000)
{
timer1s = 0;
led_buf ^= 0x40;
}
if(timer10ms >= 10)
{
timer10ms = 0;
temp = read_pcf8591(1);
dig_buf[2][5] = temp / 100;
dig_buf[2][6] = temp / 10 % 10;
dig_buf[2][7] = temp % 10;
}
}
}
4、温度DS18B20
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "onewire.h"
sbit DQ = P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
unsigned int rd_temperature(void)
{
unsigned int M,L;
unsigned int temp;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
L = Read_DS18B20();
M = Read_DS18B20();
temp = (unsigned int)M << 8 | L;
return (float)temp * 6.25;
}
#include <STC15F2K60S2.H>
#include "hardwork.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
void init()
{
P0 = 0x00; //关闭蜂鸣器和继电器
P2 |= 0xA0;
P2 &= ~0xE0;
P0 = 0xFF; //关闭LED
P2 |= 0x80;
P2 &= ~0xE0;
}
void main()
{
unsigned int temperature = 0;
init();
Timer1Init();
while(1)
{
if(timer1s >= 1000)
{
timer1s = 0;
led_buf ^= 0x40;
}
if(timer10ms >= 10)
{
timer10ms = 0;
temperature = rd_temperature();
/* 按键区域 *///end
//数码管显示
dig_buf[3][3] = temperature / 1000;
dig_buf[3][4] = temperature / 100 % 10 + 32;
dig_buf[3][5] = temperature / 10 % 10;
dig_buf[3][6] = temperature % 10;
}
}
}
5、超声波
unsigned char a = 37;
void DelayUltrasonic() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = a;
while (--i);
}
int read_distance()
{
int distance = -1; //超出测量距离
unsigned int time = 0;
//定时器初始化
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
//发送
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
P10 = 1; DelayUltrasonic(); P10 = 0; DelayUltrasonic();
//等待
TR0 = 1; //清除TF1的标志
while((P11 == 1) && (TF0 == 0));
TR0 = 0; //定时器PCA停止计时
//计算距离
if(TF0 == 0) //没有超过距离
{
time = TL0 | (TH0 << 8); //微秒
distance = time * 0.17F; //毫米
}
return distance;
}
while(1)
{
if(timer10ms >= 10)
{
timer10ms = 0;
key_scan();
if(key_value == 4 && key_state == 2)
{
a++;
}
if(key_value == 5 && key_state == 2)
{
a--;
}
if(timer100ms >= 100)
{
timer100ms = 0;
distance = read_distance();
}
if(distance >= 0) //没有超测量距离
{
digs[0] = distance / 10000;
digs[1] = distance / 1000 %10;
digs[2] = distance / 100 %10;
digs[3] = distance / 10 % 10;
}
else // 超过测量距离
{
digs[0] = 17;
digs[1] = 17;
digs[2] = 17;
digs[3] = 17;
digs[4] = 17;
}
digs[6] = a / 10 % 10;
digs[7] = a % 10;
}
}