小王子實戰@簡易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);
}
}
|