15。定时器做计数器
tim.c
#include "tim.h"
u32 Count_T1 = 0;
//void TIM1_Count_Init(void)
//{
// T1_CT = 1; //设置外部计数
// T1_M1 = 0; //设置模式为16位自动重载
// T1_M0 = 0;
// T1_GATE = 0;
//
// TH1 = (65536-Count_num)>>8; //65526
// TL1 = (65536-Count_num);
//
// P3PU |= 0x20;
//
// TR1 = 1;
// ET1 = 1; //定时器/计数器T1的中断允许位
//}
//void Timer1_Isr(void) interrupt 3
//{
// Count_T1++; //T1引脚检测到10个脉冲就会溢出一次
//}
////定时器1计数
//void T1_RunTask(void)
//{
// u32 count_th_tl = 0;
// count_th_tl = ((u16)TH1<<8) + (u16)TL1;
// count_th_tl -= 65526;
//
// SEG7_ShowLong(Count_T1 * Count_num + count_th_tl, 10);
//}
/*
任务2:编写INT1测量低电平时间
由按键模拟信号,100us的计数周期计数
*/
void Timer1_Isr(void) interrupt 3
{
static u32 count_p33 = 0; //p33计数变量初始值为0
if(P33 == 0) //按键按下计数
{
count_p33 ++;
}
else
{
if(count_p33 > 0)
{
Count_T1 = count_p33;
}
count_p33 = 0;
}
}
void Timer1_Init(void) //100微秒@24.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x38; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
//数码管输出Count_T1值
void T1_RunTask(void)
{
//SEG7_ShowLong(Count_T1 , 10); //整数输出
SEG7_ShowString("%07.01f",((float)Count_T1)/10);
}
930931
15.定时器做计数器 课后小练
借鉴坛友乐高的课后作业
课后小练
编译器一直有一个警告,消不掉。
CT计数器:
在设备的出料端口有一个感应器,每次有成品出来就会有一个低电平出来,计算相邻的两个产品出来的时间差来计算CT时间。
1.计算P33引脚的相邻两次按下的时间,精确到100ms(即单个时间)
2.计算按下P33的次数(即总产量)
3.数码管前四位显示单个时间 ,后四位显示次数
tim.c
#include "tim.h"
#include "io.h"
extern u32 Count_INT1; // 从io.c外部引用,用于存储总产量计数
u32Count_T1 = 0; // 定时器1计数值(每10ms加1)
u32Count1 = 0; // 暂存的时间计数值
extern u32 Count; // 从io.c外部引用,用于存储CT时间(100ms单位)
void INT1_Isr(void) interrupt 2
{
Count1 = Count_T1;
if(Count1 >5)
{
Count = Count1/10;
Count_INT1++;
}
Count_T1 = 0;
}
void Ext_Init(void)
{
IT1 = 1; //INT1(P3.3)下降沿中断
EX1 = 1; //使能INT1中断
}
void Timer1_Isr(void) interrupt 3
{
Count_T1++;
}
void Timer1_Init(void) //100微秒@24.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xA0; //设置定时初始值
TH1 = 0xF6; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
932
16 DS18b20测温
18b20.c
#include "18b20.h"
u8MinusFlag = 0; //温度正负标志位,等于0为正数,等于1为负数
u32 Temp_18b20; //最终温度,放大了10000倍
void Delay480us(void) //@24.000MHz
{
unsigned long edata i;
_nop_();
_nop_();
_nop_();
i = 2878UL;
while (i) i--;
}
void Delay60us(void) //@24.000MHz
{
unsigned long edata i;
_nop_();
_nop_();
_nop_();
i = 358UL;
while (i) i--;
}
void Delay1us(void) //@24.000MHz
{
unsigned long edata i;
_nop_();
_nop_();
_nop_();
i = 4UL;
while (i) i--;
}
//复位(输出0保持480us,输出1保持60us,读取当前电平,延时420us)
void DS18B20_Reset(void)
{
u8 flag = 1;
while(flag) //只要括号里的变量大于0,就会一直执行
{
DQ = 0;
Delay480us();
DQ = 1;
Delay60us();
flag = DQ;
Delay480us();
}
}
//写逻辑0(输出0保持60us+,输出1保持1us+)
void DS18B20_Write_0(void)
{
DQ = 0;
Delay60us();
DQ = 1;
Delay1us();
Delay1us();
}
//写逻辑1(输出0保持1us+,输出1保持60us+)
void DS18B20_Write_1(void)
{
DQ = 0;
Delay1us();
Delay1us();
DQ = 1;
Delay60us();
}
//读逻辑0/1(输出0保持1us+,输出1保持1us+,读取当前电平,延时60us)
bit DS18B20_Read(void)
{
bit state = 0;
DQ = 0;
Delay1us();
Delay1us();
DQ = 1;
Delay1us();
Delay1us();
state = DQ; //暂存这个DQ的值
Delay60us();
return state; //读取单个位的数据
}
//写1字节(先输出低位,在输出高位)
void DS18B20_WriteByte( u8 dat )
{
u8 i;
for(i=0;i<8;i++)
{
if( dat & 0x01 ) //最低位是1,发逻辑1电平
{
DS18B20_Write_1();
}
else //否则,发逻辑0电平
{
DS18B20_Write_0();
}
dat >>= 1; //dat = (dat>>1);
}
}
//读1字节(先读到的是低位,后读到的是高位)
u8 DS18B20_ReadByte( void )
{
u8 i;
u8 dat=0; //数据暂存
for(i=0;i<8;i++) //循环读取八次
{
dat >>= 1;
if( DS18B20_Read())
{
dat |= 0x80;
}
else
{
}
}
return dat;
}
//温度读取换算函数
//(复位-CCH-44H-等待-复位-CCH-BEH-读取2字节温度数据-换算)
void DS18B20_ReadTemp(void)
{
u8TempH = 0;
u8TempL = 0;
u16 Temp = 0;
//-----------------发送检测命令--------------------------
DS18B20_Reset(); //1,发送复位命令
DS18B20_WriteByte(0xcc); //2,跳过ROM命令
DS18B20_WriteByte(0x44); //3.开始转化命令
while(!DQ); //4.等待引脚变成高电平
//-----------------发送读取命令---------------------------
DS18B20_Reset(); //1,发送复位命令
DS18B20_WriteByte(0xcc); //2,跳过ROM命令
DS18B20_WriteByte(0xBE); //3.开始读取命令
TempL = DS18B20_ReadByte(); //读取低字节温度
TempH = DS18B20_ReadByte(); //读取高字节温度
if( TempH & 0x80 ) //如果最高位是1,这个就是负数
{
MinusFlag = 1; //标志位1,温度为负
Temp = (((u16)TempH << 8) | ((u16)TempL << 0)); //两个八位转换为16位
Temp = (~Temp)+1; //负数补码,取反加1
Temp_18b20 = (u32)Temp*625; //最终温度
}
else
{
MinusFlag = 0; //标志位1,温度为正
Temp = (((u16)TempH << 8) | ((u16)TempL << 0)); //两个八位转换为16位
Temp_18b20 = (u32)Temp*625; //最终温度
}
}940
16.DS18b20测温 课后小练 测温计 参考坛友“乐高”的16课课后小练代码
io.c
#include "io.h"
#include "18b20.h"
u8 Key_vol = 0;
u8MinusFlag;
u8 SEG_NUM[] = //不带小数点
{
0x3F, /*'0', 0*/
0x06, /*'1', 1*/
0x5B, /*'2', 2*/
0x4F, /*'3', 3*/
0x66, /*'4', 4*/
0x6D, /*'5', 5*/
0x7D, /*'6', 6*/
0x07, /*'7', 7*/
0x7F, /*'8', 8*/
0x6F, /*'9', 9*/
0x77, /*'A', 10*/
0x7C, /*'B', 11*/
0x39, /*'C', 12*/
0x5E, /*'D', 13*/
0x79, /*'E', 14*/
0x71, /*'F', 15*/
0x54, /*'N', 16*/
0x5C, /*'O', 17*/
0x73, /*'P', 18*/
0x50, /*'R', 19*/
0x40, /*'-', 20*/
0x00, /*' ', 21*/
0x80, /*'.', 22*/
};
u8 SEG_NUM1[] = //带小数点
{
0xBF, /*'0', 0*/
0x86, /*'1', 1*/
0xDB, /*'2', 2*/
0xCF, /*'3', 3*/
0xE6, /*'4', 4*/
0xED, /*'5', 5*/
0xFD, /*'6', 6*/
0x87, /*'7', 7*/
0xFF, /*'8', 8*/
0x6F, /*'9', 9*/
0x77, /*'A', 10*/
0x7C, /*'B', 11*/
0x39, /*'9', 12*/
0x5E, /*'D', 13*/
0x79, /*'E', 14*/
0x71, /*'F', 15*/
0x40, /*'-', 16*/
0x00, /*' ', 17*/
0x80, /*'.', 18*/
};
u8 T_NUM =
{
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
};
void Init_595(void)
{
HC595_SER= 0;
HC595_RCK= 0;
HC595_SCK= 0;
}
void Send_595( u8 dat )
{
u8 i;
for( i=0; i<8; i++ )
{
dat <<= 1; //数值左移一位
HC595_SER= CY; //数据写到引脚
HC595_SCK= 1; //输出上升沿的时钟信号
HC595_SCK= 0;
}
}
void Display_Seg( u8 HC595_1,u8 HC595_2)
{
Send_595(HC595_1); //数码管段码输出 高电平点亮
Send_595(HC595_2); //数码管位码输出 低电平点亮
HC595_RCK= 1; //数据输出
HC595_RCK= 0;
}
u8 passward = { 21,21,21,21,21,21,21,21};
u8 Seg_no = 0;
void SEG_Task0(void) //未开机,熄屏
{
switch(Seg_no)
{
case 0: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 1: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 2: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 3: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 4: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 5: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 6: Display_Seg( SEG_NUM1, ~T_NUM ); break;
case 7: Display_Seg( SEG_NUM, ~T_NUM ); break;
}
}
void SEG_Task1(void) ////开机2秒内显示"---C"
{
switch(Seg_no)
{
case 0: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 1: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 2: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 3: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 4: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 5: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 6: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 7: Display_Seg( SEG_NUM, ~T_NUM ); break;
}
}
void SEG_Task2(void) ////开机2秒内显示"---F"
{
switch(Seg_no)
{
case 0: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 1: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 2: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 3: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 4: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 5: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 6: Display_Seg( SEG_NUM, ~T_NUM ); break;
case 7: Display_Seg( SEG_NUM, ~T_NUM ); break;
}
}
void SEG_Task3(void) //开机2秒后正常显示摄氏温度
{
switch(Seg_no)
{
case 0: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 1: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 2: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 3: if(MinusFlag)
Display_Seg( SEG_NUM, ~T_NUM ); break;
case 4: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 5: Display_Seg( SEG_NUM1], ~T_NUM ); break;
case 6: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 7: Display_Seg( SEG_NUM, ~T_NUM ); break;
}
}
void SEG_Task4(void) //开机2秒后正常显示华氏温度
{
switch(Seg_no)
{
case 0: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 1: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 2: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 3: if(MinusFlag)
Display_Seg( SEG_NUM, ~T_NUM ); break;
case 4: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 5: Display_Seg( SEG_NUM1], ~T_NUM ); break;
case 6: Display_Seg( SEG_NUM], ~T_NUM ); break;
case 7: Display_Seg( SEG_NUM, ~T_NUM ); break;
}
}
u16 Timing = 0; //计时
bit Temp_C_F; //温度标志位,1(真)华氏,0(假)摄氏
bit run = 0; //开关机标志位,0关机,1开机
void SEG_Show(void)
{
u8 num =0;
if(run == 0) //没有按下开机键
{
Timing = 0;
SEG_Task0(); //执行息屏函数
}
else
{
Timing++;
if(Timing>2000)
{
if(Temp_C_F)
SEG_Task4();
else
SEG_Task3();
Timing = 2000;
}
else
{
if(Temp_C_F)
SEG_Task2();
else
SEG_Task1();
}
}
Seg_no ++;
if( Seg_no>7 )
Seg_no=0;
}
void SEG_Show_U32(u32 num)
{
u8 i;
for(i=0; i<3;i++)
{
passward = num%10;
num /= 10;
}
}
//u8 Key_Vol3 = 0; //判断按钮是否按下
u8 Key_no = 0; //数码管位计数
u16 key_num;
void KEY_Task(void)
{
//---------------开关机-------------------------
if(Temp_C_F == 0)
SEG_Show_U32(Temp_18b20);
else
SEG_Show_U32(Temp_F);
if(P01 == 0)
{
if(P01 == 0)
{
run = !run;
key_num = 0;
}
while(P01 == 0);
}
//---------------华氏摄氏转换-------------------------
key_num++;
if(P03 == 0)
{
Key_vol++;
key_num = 0;
if(Key_vol == 5)
{
Temp_C_F = !Temp_C_F;
}
}
else
Key_vol = 0;
if(key_num == 3000)
run = 0;
}
941
17.串口的简单应用
usart.c
#include "usart.h"
#include "io.h"
u8 Rec_Dat; //接收缓冲区
u8 Rec_Num = 0; //接收计数
bit B_TX2_Busy = 0; //发送完成标志位
void Uart2_Isr(void) interrupt 8
{
if (S2CON & 0x02) //检测串口2发送中断
{
S2CON &= ~0x02; //清除串口2发送中断请求位
B_TX2_Busy = 0; //发送完成清零
}
if (S2CON & 0x01) //检测串口2接收中断
{
S2CON &= ~0x01; //清除串口2接收中断请求位
Rec_Dat = S2BUF;
}
}
void Uart2_Init(void) //9600bps@24.000MHz
{
P_SW2 |= 0x01; //UART2/USART2: RxD2(P4.2), TxD2(P4.3)
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x8F; //设置定时初始值
T2H = 0xFD; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x01; //使能串口2中断
B_TX2_Busy = 0;
Rec_Num = 0;
}
void Uart2_SendStr(u8 *puts) //串口数据发送函数
{
for (; *puts != 0;puts++) //遇到停止符0结束
{
S2BUF = *puts;
B_TX2_Busy = 1;
while(B_TX2_Busy);
}
}
/*
1.发送OPEN\r\n打开数码管,数码管显示“- - - -”
思路:判断发送的数据最后六位,是否等于open\r\n,只要检测到OPEN\r\n ,
OPEN前面的数据都可以忽略不计
2.发送CLOSE\r\n打开数码管,数码管全部熄灭
*/
void Usart2_RunTask(void)
{
if(Rec_Num >= 6) //是否接收到了6位以上的数据
{
if((Rec_Dat == '\n') && (Rec_Dat == '\r')) //数据末尾判断
{
if((Rec_Dat == 'O') && (Rec_Dat == 'P') && (Rec_Dat == 'E') && (Rec_Dat == 'N'))
{
passward = 20;
passward = 20;
passward = 20;
passward = 20;
Uart2_SendStr("打开成功\r\n");
}
else if((Rec_Dat == 'C') && (Rec_Dat == 'L') && (Rec_Dat == 'O') && (Rec_Dat == 'S') && (Rec_Dat == 'E'))
{
passward = 21;
passward = 21;
passward = 21;
passward = 21;
Uart2_SendStr("关闭成功\r\n");
}
Rec_Num = 0;
}
}
}943
17.串口的简单应用课后小练 智能数码管显示屏
void Usart2_RunTask(void)
void Usart2_RunTask(void)
{
if(Rec_Num >= 6) //是否接收到了6位以上的数据
{
if((Rec_Dat == '\n') && (Rec_Dat == '\r')) //数据末尾判断
{
if((Rec_Dat == 'O') && (Rec_Dat == 'P') && (Rec_Dat == 'E') && (Rec_Dat == 'N'))
{
passward = 20;
passward = 20;
passward = 20;
passward = 20;
Uart2_SendStr("打开成功\r\n");
}
else if((Rec_Dat == 'C') && (Rec_Dat == 'L') && (Rec_Dat == 'O') && (Rec_Dat == 'S') && (Rec_Dat == 'E'))
{
passward = 21;
passward = 21;
passward = 21;
passward = 21;
Uart2_SendStr("关闭成功\r\n");
}else if((Rec_Dat == 'D') &&(Rec_Dat == 'A') &&(Rec_Dat == 'T') && (Rec_Dat == '+') && (Rec_Dat == '1') && (Rec_Dat == '2') && (Rec_Dat == '3'))
{
passward = 1;
passward = 2;
passward = 3;
// passward = 21;
Uart2_SendStr("发送成功\r\n");
}
Rec_Num = 0;
}
}
}944