小王子实战@简易1kHz至1MHz方波信号频率计
/***********************************************************
* 实验名称及内容:简易1kHz至1MHz方波信号频率计
* 配套书籍:《深入浅出STM8单片机入门、进阶与应用实例》
* 实验平台及编程人员:思修电子工作室"祥云小王子"开发版 Long
***************************************************************/
#include "iostm8s208mb.h"//主控芯片的头文件
/************************常用数据类型定义**********************/
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
/***********************端口/引脚定义区域**********************/
#define LCDRS PF_ODR_ODR0 //LCD1602数据/命令选择端口
#define LCDRW PF_ODR_ODR3 //LCD1602读写控制端口
#define LCDEN PF_ODR_ODR4 //LCD1602使能信号端口
#define LCDDATA PB_ODR //LCD1602数据端口D0至D7
/**********************用户自定义数据区域**********************/
u8 table1[]="=Frequency Test=";//LCD1602显示字符串数组1显示界面
u8 table2[]="f: Hz";//LCD1602显示字符串数组2显示界面
u8 table3[]={'0','1','2','3','4','5','6','7','8','9'};//数字字符
static u16 A_num,B_num,SYS_num;//定义A_num、B_num变量用于装载两次边沿时间
//SYS_num用于存放周期计数值
static unsigned long F_num;//用于存放频率值
#define SYS_CLOCK 8034400UL//定义系统当前fmaster频率值
/************************函数声明区域*************************/
void delay(u16 Count);//延时函数声明
void GPIO_init(void);//GPIO端口初始化配置函数声明
void TIM1_init(void);//TIM1初始化函数声明
void LCD1602_init(void);//LCD1602初始化函数
void LCD1602_DIS_CHAR(u8 x,u8 y,u8 z);//在设定地址写入字符数据
void LCD1602_Write(u8 cmdordata,u8 writetype);//写入液晶模组命令或数据
void LCD1602_DIS(void);//显示字符函数
/**************************主函数区域*************************/
int main(void)
{
u8 i,baiwan,shiwan,wan,qian,bai,shi,ge;//i为循环控制,其它为取位变量
CLK_CKDIVR=0x08;//设置系统时钟为HSI内部8MHz时钟
delay(10);//延时等待稳定
GPIO_init();//初始化相关GPIO引脚配置
LCD1602_init();//LCD1602初始化
LCD1602_DIS();//显示字符
TIM1_init();//TIM1相关功能配置初始化
TIM1_CCER1&=0xFE;//捕获功能禁止
LCD1602_Write(0xC0,0);//选择第二行
for(i=0;i<16;i++)
{
LCD1602_Write(table2[ i],1);//写入table2[]内容
delay(5);
}
while(1)
{
TIM1_CCR1H=0x00;//清除捕获/比较寄存器1高8位
TIM1_CCR1L=0x00;//清除捕获/比较寄存器1低8位
TIM1_CCER1|=0x01;//捕获功能使能
while((TIM1_SR1&0x02)==0);//等待捕获比较1标志位CC1IF变为“1”
A_num=(u16)TIM1_CCR1H<<8;//取回捕获/比较寄存器1高8位
A_num|=TIM1_CCR1L;//取回捕获/比较寄存器1低8位并与高8位拼合
while((TIM1_SR1&0x02)==0);//等待捕获比较1标志位CC1IF变为“1”
B_num=(u16)TIM1_CCR1H<<8;//取回捕获/比较寄存器1高8位
B_num|=TIM1_CCR1L;//取回捕获/比较寄存器1低8位并与高8位拼合
TIM1_CCER1&=0xFE;//捕获功能禁止
SYS_num=B_num-A_num;//得到信号周期计数值
F_num=(8*SYS_CLOCK)/SYS_num;//计算频率值
baiwan=F_num/1000000;//取出百万位
shiwan=F_num%1000000/100000;//取出十万位
wan=F_num%100000/10000;//取出万位
qian=F_num%10000/1000;//取出千位
bai=F_num%1000/100;//取出百位
shi=F_num%100/10;//取出十位
ge=F_num%10;//取出个位
LCD1602_DIS_CHAR(2,4,table3[baiwan]);//百万位显示到2行第4字符位
LCD1602_DIS_CHAR(2,5,'.');//显示分隔小数点
LCD1602_DIS_CHAR(2,6,table3[shiwan]);//十万位显示到2行第6字符位
LCD1602_DIS_CHAR(2,7,table3[wan]);//万位显示到2行第7字符位
LCD1602_DIS_CHAR(2,8,table3[qian]);//千位显示到2行第8字符位
LCD1602_DIS_CHAR(2,9,'.');//显示分隔小数点
LCD1602_DIS_CHAR(2,10,table3[bai]);//百位显示到2行第10字符位
LCD1602_DIS_CHAR(2,11,table3[shi]);//十位显示到2行第11字符位
LCD1602_DIS_CHAR(2,12,table3[ge]);//个位显示到2行第12字符位
}
}
/****************************************************************/
//延时函数delay(),有形参Count用于控制延时函数执行次数,无返回值
/****************************************************************/
void delay(u16 Count)
{
u8 i,j;
while (Count--)//Count形参控制延时次数
{
for(i=0;i<50;i++)
for(j=0;j<20;j++);
}
}
/****************************************************************/
//GPIO端口初始化配置函数GPIO_init(),无形参,无返回值
/****************************************************************/
void GPIO_init(void)
{
//1.配置LCD1602数据口PB
PB_DDR=0xFF; //配置PB端口为输出端口
PB_CR1=0xFF; //配置PB端口为推挽输出模式
PB_CR2=0x00; //配置PB端口为低速斜率输出
LCDDATA=0xFF;//初始化PB端口全部输出高电平
//2.配置LCD1602液晶RS引脚
PF_DDR_DDR0=1;//配置PF0为输出模式
PF_CR1_C10=1; //配置PF0为推挽输出模式
PF_CR2_C20=0; //配置PF0低速率输出
//3.配置LCD1602液晶RW引脚
PF_DDR_DDR3=1;//配置PF3为输出模式
PF_CR1_C13=1; //配置PF3为推挽输出模式
PF_CR2_C23=0; //配置PF3低速率输出
LCDRW=0; //配置LCD1602为写入模式
//4.配置LCD1602液晶EN引脚
PF_DDR_DDR4=1;//配置PF4为输出模式
PF_CR1_C14=1; //配置PF4为推挽输出模式
PF_CR2_C24=0; //配置PF4低速率输出
}
/****************************************************************/
//TIM1功能初始化函数TIM1_init(),无形参,无返回值
/****************************************************************/
void TIM1_init(void)
{
//1.CC1通道被配置为输入,IC1映射在TI1FP1上“CC1S[1:0]=01”
TIM1_CCMR1|=0x01;
//2.配置采样率为主时钟频率,无滤波器“IC1F[3:0]=0000”
TIM1_CCMR1&=0x0F;
//3.配置信号边沿极性为TI1F或TI2F的低电平或下降沿“CC1P=1”
TIM1_CCER1|=0x02;
//4.配置输入/捕获1通道预分频器因子为8分频“IC1PSC[1:0]=11”
TIM1_CCMR1|=0x0C;
//5.使能TIM1_CH1输入捕获功能“CC1E=1”
TIM1_CCER1|=0x01;
//6.使能TIM1计数器功能“CEN=1”
TIM1_CR1|=0x01;
}
/****************************************************************/
//LCD1602初始化函数LCD1602_init(),无形参和返回值
/****************************************************************/
void LCD1602_init(void)
{
LCD1602_Write(0x38,0);//配置16*2显示,5*7点阵,8位数据接口
LCD1602_Write(0x0C,0);//设置开显示,不显示光标
LCD1602_Write(0x06,0);//写字符后地址自动加1
LCD1602_Write(0x01,0);//显示清0,数据指针清0
}
/****************************************************************/
//设定地址写入字符函数LCD1602_DIS_CHAR(),有形参x、y、z无返回值
//x表示1602液晶的行,y表示列地址,z表示欲写入的字符
/****************************************************************/
void LCD1602_DIS_CHAR(u8 x,u8 y,u8 z)
{
u8 address;
if(x==1)//若欲显示在第一行
address=0x80+y;//第一行的行首地址+列地址
else
address=0xC0+y;//第二行的行首地址+列地址
LCD1602_Write(address,0);//设定显示地址
LCD1602_Write(z,1);//写入字符数据
}
/****************************************************************/
//写入液晶模组命令或数据函数LCD1602_Write(),有形参cmdordata和
//writetype,无返回值。
/****************************************************************/
void LCD1602_Write(u8 cmdordata,u8 writetype)
{
if(writetype==0)//判断写入类型
LCDRS=0;//写入命令信息
else
LCDRS=1;//写入数据信息
LCDDATA=cmdordata;//向数据线端口写入信息
delay(5);//延时等待稳定
LCDEN=1;//模块使能
delay(5);//延时等待写入
LCDEN=0;//模块不使能
}
/****************************************************************/
//显示字符函数LCD1602_DIS(),无形参和返回值
/****************************************************************/
void LCD1602_DIS(void)
{
u8 i;//定义控制循环变量i
LCD1602_Write(0x80,0);//选择第一行
for(i=0;i<16;i++)
{
LCD1602_Write(table1[ i],1);//写入table1[]内容
delay(5);
}
LCD1602_Write(0xC0,0);//选择第二行
for(i=0;i<16;i++)
{
LCD1602_Write('>',1);//带延时逐一显示字符“>”模拟进度条
delay(50);
}
}
|