📄 mcs51-项目开发经典.c
字号:
//=================================================================================================
// 项目名:MCS51-项目开发经典
// 硬件文件名:51Studay.DDB
// 程序组目录名:MCS51-项目开发经典
// 开始时间:2007年5月21日
// 完成时间:2007年6月10日
//-------------------------------------------------------------------------------------------------
// 程序中用到哪些C51标准函数,就需要把该函数对应的头文件包含进来
//-------------------------------------------------------------------------------------------------
#include <intrins.h>
#include <string.h>
#include <absacc.h>
#include <reg52.h>
//-------------------------------------------------------------------------------------------------
// 为提高书写效率做以下宏定义
//-------------------------------------------------------------------------------------------------
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define CLOSE 1
#define OPEN 0
//-------------------------------------------------------------------------------------------------
// HD7279操控位及指令宏定义
//-------------------------------------------------------------------------------------------------
sbit CS_7279 = P1^0;
sbit CLK_7279 = P1^1;
sbit DATA_7279= P1^2;
sbit KEY_7279 = P1^3;
// HD7279指令宏定义:不带数据的纯指令
#define HD7279_RESET 0xa4 //复位,相当于重新上电
#define HD7279_TEST 0xbf //测试,点亮全部LED并闪烁
#define HD7279_RL 0xa1 //左移1位
#define HD7279_RR 0xa0 //右移1位
#define HD7279_RLC 0xa3 //循环左移
#define HD7279_RRC 0xa2 //循环右移
// HD7279指令宏定义:带有数据的指令
#define HD7279_DECODE0 0x80 //译码方式0
#define HD7279_DECODE1 0xc8 //译码方式1
#define HD7279_UNDECODE 0x90 //译码方式2: 不译码
#define HD7279_FLASH 0x88 //闪烁指令,后跟8位数据 D8|D7|D6|D5|D4|D3|D2|D1,某位置0则该位闪烁
#define HD7279_HIDE 0x98 //消隐指令,后跟8位数据 D8|D7|D6|D5|D4|D3|D2|D1,某位置0则该位消隐
#define HD7279_SEGON 0xe0 //单段亮
#define HD7279_SEGOFF 0xc0 //单段灭
#define HD7279_READ_KEY 0x15 //读按键代码,读出的数值对应按下的键,无键按下时数值为0xff.
//=================================================================================================
#define TEST_74HC595 1
#define TEST_24C02 2
#define TEST_93C46 3
#define SET_SD2000 4
#define READ_SD2000 5
#define TEST_18B20 6
#define TEST_HD7279 7
#define TEST_BIT_IO 8
#define TEST_TLC2543 9
#define TEST_TLC5617 10
#define TEST_PWM_DA 11
#define TEST_L297 12
#define TEST_DC_MOTOR 13
#define TEST_LCM 14
//-------------------------------------------------------------------------------------------------
// 操作UART串口相关的全局变量
//-------------------------------------------------------------------------------------------------
uchar idata uart_buffer[40];//串口接收缓冲区,可接收字符串的最大长度为40
uchar uart_buffer_address;//串口接收缓冲区地址计数器
bit uart_receive_start; //串口接收启动
bit uart_receive_ok; //串口接收(UART0)中断里已接收完整消息标志
bit kaiguan;
//-------------------------------------------------------------------------------------------------
// 键盘扫描相关的全局变量
//-------------------------------------------------------------------------------------------------
uchar key_value_previous;
uchar key_press_counter;
uchar key_value_main;
uchar key_press_timer;
//-------------------------------------------------------------------------------------------------
uchar t1_delay_time;//50毫秒计数器累加变量,在T2中断里累加
bit i2c_response_signal;//I2C总线应答信号
uint idata temporary_data[10];//临时数据
uchar idata test_command;//存储串口接收的测试命令
uchar idata weizhi;
uint motor_speed_delay;
//-------------------------------------------------------------------------------------------------
// 函数声明
//-------------------------------------------------------------------------------------------------
void init_cpu(void);
void ctrl_74hc595(uchar led_display_data);
void HD7279_LongDelay(void);
void HD7279_ShortDelay(void);
void HD7279_SendByte(uchar out_byte);
uchar HD7279_ReceiveByte(void);
uchar HD7279_GetKey(void);
void HD7279_ShowData(uchar Position,uchar ShowData,bit Have_DP);
void HD7279_Showflash(uchar Position_flash);
void HD7279_Initial(void);
void uart_byte_out(uchar uart_data_out);
void uart_string_out(char * char_array);
void uart_data_decimalist_out(uint data_to_out);
void uart_newline(uchar newline_number);
void uart_space(uchar space_number);
uchar change_bcd_to_hex(uchar shu);
uchar change_hex_to_bcd(uchar shu);
uchar change_askii_to_hex(uchar askii);
uchar change_hex_to_askii(uchar data_hex);
void get_data(uchar * how_much_data);
char * strstr(char * haystack, char * needle);
//=================================================================================================
//===================== ================================================
//===================== 主程序 ================================================
//===================== ================================================
//=================================================================================================
void main (void)
{ uchar i;
init_cpu();
HD7279_Initial();
key_value_main=0xff;
HD7279_SendByte( HD7279_RESET );//复位
wqyloop:
for(i=0;i<10;i++) //数码管测试
{ HD7279_ShowData(1,i,1);
HD7279_ShowData(2,i,1);
HD7279_ShowData(3,i,1);
HD7279_ShowData(4,i,1);
HD7279_ShowData(5,i,1);
HD7279_ShowData(6,i,1);
HD7279_ShowData(7,i,1);
HD7279_ShowData(8,i,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
}
HD7279_ShowData(1,1,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
HD7279_ShowData(2,2,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
HD7279_ShowData(3,3,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
HD7279_ShowData(4,4,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
HD7279_ShowData(5,5,1);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
HD7279_Showflash(3);
for(t1_delay_time=0;t1_delay_time<10;);//延时500毫秒
if(key_value_main!=0xff)//如果有按键触发则如下
{uart_string_out("You have pushed the button S");
uart_byte_out(change_hex_to_askii(key_value_main));
uart_newline(1);
key_value_main=0xff;//使用完本次触发的键值后必须清空键值,否则主程序认为在连续触发该键
}
goto wqyloop;
}//The end of main()
//########################## 主程序结束 #########################################################
//########################## 子程序开始 #########################################################
//=================================================================================================
// 函数功能:CPU初始化函数
// 串口波特率可以由T1或T2产生,本例中用T1产生波特率
// T2用于50毫秒精确定时
// T0用于PWM控制中频率的时基
//=================================================================================================
void init_cpu(void)
{
TMOD=0x12;//T1为16位计数器,T0为8位自动重装载计数器
ET1=1;
TH1=0x4c;//11.0592M晶振时T1定时时间长度为50毫秒
TL1=0x00;
TR1=1;//T1开始定时
T2CON=0x30;//定时器T2工作于波特率发生器方式
RCAP2H=0xff;//11.0592M晶振,9600bps初值
RCAP2L=0xdc;
TH2=0xff;
TL2=0xdc;
//RCAP2H=0xfe;//11.0592M晶振,1200bps初值
//RCAP2L=0xe0;
//TH2=0xfe;
//TL2=0xe0;
TR2=1;//允许T2中断
ES=1; //串口中断允许
PS=1; //串口中断优先级设为高,因为要通过串口干预程序流程,为保证可靠接收所以有此设置
SCON=0x50;//串口工作于方式1,启动串口接收
EA=1;//CPU中断开放
//以下是程序中软件逻辑需要的变量初值设置和硬件初始状态设置
key_value_main=0xff;
}
//=================================================================================================
// 以下是HD7279驱动程序
// 操作HD7279的关键是如何保证手册中给定的T1到T8这8个时间间隔
// 并且只有当HD7279的27脚外接R=1。5K、C=15P时,T1到T8才是手册中给的数值,建议不要随意改变R、C的值
// 弄清楚这个问题,则你对器件时序图的理解将上升到一个新的高度。任何器件的驱动程序只要看懂时序图就OK!
//=================================================================================================
// 函数功能:长延时,保证延时时间在50~250uS之间
void HD7279_LongDelay(void)
{ uchar i;
for (i=0;i<30;i++);
}
//-------------------------------------------------------------------------------------------------
// 函数功能:短延时,保证延时时间在8~250uS之间
void HD7279_ShortDelay(void)
{ uchar i;
for (i=0;i<8;i++);
}
//-------------------------------------------------------------------------------------------------
//函数功能:向HD7279写字节
void HD7279_SendByte(uchar out_byte)
{ uchar i;
CLK_7279=0;//准备CLK脚状态
CS_7279=0; //准备CS脚状态,置0允许操作7279
HD7279_LongDelay();//延时T1,在带数据的命令中此延时相当于送数据之前的T4延时
for(i=0;i<8;i++)
{if(out_byte&0x80) DATA_7279=1;//准备数据,高位MSB先入
else DATA_7279=0;
CLK_7279=1;//CLK_7279下降沿时DATA_7279数据写入
HD7279_ShortDelay();//延时T2
CLK_7279=0;
HD7279_ShortDelay();//延时T3
out_byte<<=1;//准备要写入数据的次高位
}
}
//-------------------------------------------------------------------------------------------------
//函数功能:从HD7279读字节,只在读键值时用到
uchar HD7279_ReceiveByte(void)
{ uchar i;
uchar in_byte;
DATA_7279=1;//置单片机DATA_7279端为输入状态
HD7279_LongDelay();//延时T5
for(i=0;i<8;i++)
{CLK_7279=1;
HD7279_ShortDelay();//延时T7(因为T7=T6),此延时结束后HD7279_DATA数据才有效,
in_byte=in_byte<<1;//键值的高位MSB先出,因为最低位LSB取出后不需要左移,所以有此操作
if(DATA_7279) in_byte=in_byte|0x01;//取HD7279_DATA的数据状态,放入in_byte最低位LSB
CLK_7279=0;
HD7279_ShortDelay();//延时T3,这个延时手册中没有标出(因为T3>T8,所以最后1位取出后此T3相当于T8)
}
return (in_byte);
}
//----------------------------------------------------------------------------------------------
//函数功能:获得按键代码
uchar HD7279_GetKey(void)
{ uchar key;
HD7279_SendByte(HD7279_READ_KEY);
key=HD7279_ReceiveByte();
return(key);
}
//-------------------------------------------------------------------------------------------------
// 函数功能:按方式0译码,在指定的1到8位置显示数据
// 通常情况下我们都使用方式0译码,方式1译码与之大同小异
// 形参:Position 显示位置(1-8),ShowData 数据(0-15),Have_DP 是否显示小数点(1显示,0不显示)
void HD7279_ShowData(uchar Position,uchar ShowData,bit Have_DP)
{ uchar Decode0_data;
if(Have_DP) ShowData = ShowData|0x80;//处理小数点的显示与否
Decode0_data=(Position-1)|HD7279_DECODE0;//将译码方式0和要显示的位置合并
HD7279_SendByte(Decode0_data);//送命令
HD7279_SendByte(ShowData);//送数据
CS_7279=1;
}
//-------------------------------------------------------------------------------------------------
// 函数功能:按方式0译码,在指定的1到8位置闪烁数据
// 通常情况下我们都使用方式0译码,方式1译码与之大同小异
// 形参:Position_flash 显示位置(1-8)
void HD7279_Showflash(uchar Position_flash)
{ uchar FlashDate=0xff;
FlashDate=FlashDate&(~(0x01<<(Position_flash-1)));
HD7279_SendByte(HD7279_FLASH);//送命令
HD7279_SendByte(FlashDate);//送数据
CS_7279=1;
}
//-------------------------------------------------------------------------------------------------
//函数功能:HD7279初始化,建议在工业现场干扰严重情况下,刷新显示时先执行此命令
void HD7279_Initial(void)
{
HD7279_SendByte( HD7279_RESET );//复位
}
//=================================================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -