1、基础
#include <STC15F2K60S2.H>
#define uchar unsigned char
#define uint unsigned int
#define Y0 P2=(P2&0x1f)
#define Y4 P2=(P2&0x1f)|0x80//LED
#define Y5 P2=(P2&0x1f)|0xa0//继电器
#define Y6 P2=(P2&0x1f)|0xc0//smg
#define Y7 P2=(P2&0x1f)|0xe0//smg
2、初始化
void Init_sys()
{
Y0;P0=0xff;Y4;//关灯
Y0;P0=0x00;Y5;//关器(继电器、蜂鸣器)
Y0;
}
3、点灯
int main()
{
Y0;Y4;P0=0xff;P07=0;Y0;
}
给0灯亮,给1灯灭
P00对应灯L1,P01对应L2,同理P07对应灯L8
4、蜂鸣器
int main()
{
Y0;P0=0x00;Y5;Y0;//关闭所有器件
}
int main()
{
Y0;P04=1;Y5;Y0;//开继电器
}
int main()
{
Y0;P06=1;Y5;Y0;//开蜂鸣器
}
5、定时器
5.0定时器0
待写
5.1定时器1
频率依据题目选定,无串口一般选12MHz,
定时长度:数码管一般选1ms
定时器:0/1
模式:具有16位自动重装载,(内部资源)
定时器时钟:为12T时钟,速度更快
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
int main()
{
Timer1Init();
ET1=1;//打开定时器1的中断
EA=1;
}
void T1_int()interrupt 3
{
static uint t=0;
t++;
if(t==100)
{
t=0;Y0;P0=~P0;Y4;Y0;
}
}
5.2定时器2
首先STC15F2K60S2是有定时器2的,且掌握定时器的使用的必须的,同样,stc助手是可以生成配置文件的,
void Timer2Init(void) //2毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0x30; //设置定时初始值
T2H = 0xF8; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
}
IE2|=0x04;EA=1;是必须的
为什么不直接ET2=1?(定时器2中断允许位)
因为ET2没有单独的寄存器,它被包括在IE2的第2位
(定时器2只有16位自动重装载模式,故中断服务函数不再重写赋值)
void main()
{
Timer2Init();
IE2|=0x04;EA=1;
while(1);
}
void T2_inter()interrupt 12 //注意这里是12
{
smg(buff,0);
}
6、数码管
注:共阳数码管
static uchar digit[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0XFF};
//point==1代表某位加小数点,如下为第六位,(显示温度36.7)
void smg(uchar *buff,uchar point)
{
static uchar i=0;
Y0;P0=0xff;Y7;
Y0;P0=1<<i;Y6;
Y0;P0=digit[buff[i]];
if(point==1&&i==6)
P0+=0x80;
Y7;
if(++i==8) i=0;
}
/*---------------------------*/
uchar buff[8]= {8,9,10,0,1,2,3,4};
void main()
{
}
void T1_int()interrupt 3
{
smg(buff,1);//1ms不断扫描
}
7、PWM脉宽调制
争议:其中TL寄存器部分是65535还是65536,是255还是256,初学者容易在次产生争议
答:65536,256(已使用示波器测量确定的,读者亦可自行推导)
以下代码,测得P20输出频率为100Hz,占空比为2%
void Timer0Init(void) //@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = (65536-100)%256; //设置定时初始值
TH0 = (65536-100)/256; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Time0()interrupt 1
{
static uchar t=0;
t++;
if(t==98) P20=0;
else if(t==100) {P20=1;t=0;}
}
8、温度DS18B20
wendu
//1、第一步改写温度延时函数
void Delay_OneWire(unsigned int t)
{
t*=10;
while(t--);
}
//2、写获取温度函数
float rd_temperature(void)
{
unsigned int H,L;
init_ds18b20();
Write_DS18B20(0xcc);Write_DS18B20(0x44);Delay_OneWire(50);
init_ds18b20();
Write_DS18B20(0xcc);Write_DS18B20(0xbe);
L=Read_DS18B20();
H=Read_DS18B20();
H=(H<<8)|L;
return H/16.0;
}
//依据题目定义为float
float wendu=0;
9、实时时钟DS1302
1
void ds1302_config(uchar*t)
{
uchar addr_W=0x80,i;
Write_Ds1302_Byte(0x8e,0x00);//
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(addr_W,t[i]);
addr_W+=2;
}
Write_Ds1302_Byte(0x8e,0xff);
}
void ds1302_read(uchar*t)
{
uchar addr_W=0x81,i;
for(i=0;i<7;i++)
{
t[i]=Read_Ds1302_Byte(addr_W);
addr_W+=2;
t[i]=t[i]/16*10+t[i]%16;
}
}
//(伪代码)
uchar time[7]={0x55,0x27,0x16,0x07,0x04,0x05,0x23};//年,星期,月日,时分秒
//(数组最后是年,第一个是秒)
void main()
{
ds1302_config(time);
while(1)
{
ds1302_read(time);
buff[0]=time[2]/10;buff[1]=time[2]%10;
buff[3]=time[1]/10;buff[4]=time[1]%10;
buff[6]=time[0]/10;buff[7]=time[0]%10;
}
10、串口
10.1只发送
由于只发送,故不用开启串口中断,(涉及寄存器ES,EA,可不管)
1、STC-ISP配置如下
2、代码如下
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE8; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
}
//发送函数1字节
void usart_send(unsigned char t)
{
SBUF=t;
while(TI==0);TI=0;
}
//发送字符串
void Send_buff(uchar *dat)
{
while(*dat != '\0')
Send_Usart(*dat++);
}
//实例代码
void main()
{
UartInit();
while(1)
{
usart_send(0x0f);
Delay100ms();
}
}
10.2接收与发送
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE8; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
}
void usart_send(unsigned char t)
{
SBUF=t;
while(TI==0);TI=0;
}
void main()
{
UartInit();
ES=1;EA=1;
while(1)
{
}
}
void jieshou_usart() interrupt 4
{
if(RI==1)
{
RI=0;
usart_send(SBUF);
}
}
11、EEPROM掉电存储
待写
void write_eeprom(unsigned char add,unsigned char val)
{
IIC_Start();
IIC_SendByte(0xa0);//写
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(val);
IIC_WaitAck();
IIC_Stop();
//写完后最好延时一下
}
unsigned char read_eeprom(unsigned char add)
{
unsigned char da;
IIC_Start();
IIC_SendByte(0xa0);//写
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
//注意这里不加停止信号
IIC_Start();
IIC_SendByte(0xa1);//读
IIC_WaitAck();
da = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();//省略这个停止信号影响不大,官方是加了的
return da;
}
12、电压转换PCF8591
12.1电压读取
AIN0-外部引脚 AIN1-光敏电阻 AIN2-电源接地 AIN3-滑动变阻
uchar Read_adc()
{
uchar t;
I2CStart();
I2CSendByte(0x90);I2CWaitAck();
I2CSendByte(3);I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);I2CWaitAck();
t=I2CReceiveByte();
I2CSendAck(1);
return t;
}
电压读取这个还有另一种写法,参考官方例程,
void Init_adc()
{
I2CStart();
I2CSendByte(0x90);I2CWaitAck();
I2CSendByte(3);I2CWaitAck();
I2CStop();
}
uchar getadc()
{
uchar t;
I2CStart();
I2CSendByte(0x91);I2CWaitAck();
t=I2CReceiveByte();
I2CSendAck(1);
return t;
}
//---------------------------
void main()
{
Init_adc();
while(1)
{
dianya=getadc();
buff[0]=dianya/100;buff[1]=dianya/10%10;
buff[2]=dianya%10;
}
}
12.1电压输出
void OUT_adc(uchar viot)
{
I2CStart();
I2CSendByte(0x90);I2CWaitAck();
I2CSendByte(0x40);I2CWaitAck();//0x40代表第6位为1,电压输出DA转换
I2CSendByte(viot);I2CWaitAck();
I2CStop();
}
13、超声波测距
1
void Send_CSB()
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=1;
Delay12us();
TX=0;
Delay12us();
}
}
void main()
{
TMOD=0x10;//0001 0000
TH1=TL1=0;
Init_sys();
ET0=1;EA=1;
while(1)
{
Send_CSB();TR1=1;//jishi
while((RX==1) && (TF1==0));
TR1=0;
if(TF1==1) {TF1=0;distance=3;}
else
{
distance=TH1;
distance=((distance<<8)|TL1)*0.017;
}
TH1 = 0;
TL1 = 0;
Delay400ms();
buff[0]=distance/100;
buff[1]=distance/10%10;
buff[2]=distance%10;
}
}
14、长安剑
自写
void T0_intr()interrupt 1
{
unsigned char key_val = 0xFF;
static uchar t=0;
smg(buff);
if(++t==25)
{
t=0;now=loop(&key);
P3=0xff;P32=0;
if(status==0)
{
if(P34==0) //t=17;
status=1;
}
if(status==1)
{
if(P34==0) //t=17;
{
if(press_counter<20)
press_counter++;
}
else
{
if(press_counter>5)
status=2;
else
{
status=0;press_counter=0;
}
}
}
if(status==2)
{
if(P34==1)
{
if(press_counter<20)
real=1;
else
real=2;
status=0;
press_counter=0;
}
}
}
}
官方
//°´¼üɨÃ躯Êý
unsigned char read_key(void)
{
static unsigned int press_counter = 0; //³¤¶Ì°´¼ü¼ÆÊýÆ÷
static unsigned char status = 0;
unsigned char key_val = 0xFF;
switch(status){
case 0:
if(P33 == 0){
status = 1;
}
break;
case 1:
if(P33 == 0)
{
if(press_counter < 400)
{
press_counter++;
}
}
else
{
if(press_counter > 20)
{
status = 2;
}
else
{
status = 0; //¶¶¶¯
press_counter = 0;
}
}
break;
case 2:
if(P33 == 1)
{
if(press_counter < 400)
{
key_val = 1; //¶Ì°´¼ü
}
else
{
key_val = 2 ; //³¤°´¼ü
}
status = 0;
press_counter = 0;
}
break;
}
return key_val;
}