深圳市赛元微电子股份有限公司工具与软件/软件开发工具/下载KEIL(C51)插件安装包SOC_KEIL_Setup并安装,自动安装到KEIL C51安装路径(先安装KEIL C51软件),安装成功后在Keil C51软件安装目录下就会有赛元SOC 51单片机DEMO示例。
SOC_KEIL_Setup V1.40(LIB0D29) KEIL 插件V1.40中文rar7.2MB2023-11-22下载
初始化
建议使用位运算可以更方便得使某一位寄存器位bit置1或置0而不影响同寄存器其他位bit
以SC92F73A3_73A2_73A1_Demo_Code为例
1、IO口初始化(配置PxCON、PxPH寄存器)
P0CON = 0xF0;//二进制11110000,表示管脚P0.0到P0.3为输入模式,P0.4到P0.7为强推挽输出模式,想要输入模式对应管脚置0,输入模式对应管脚置1
P0PH = 0xF0;//二进制11110000,表示管脚P0.0到P0.3为高阻输入模式,P0.4到P0.7为上拉电阻打开模式(仅在管脚输入模式时有效),想要高阻输入模式对应管脚置0,上拉电阻打开模式对应管脚置1
IO口初始化有强推挽输出模式,带上拉输入模式,高阻输入模式,错误配置会导致ADC输入数据不准确,IO口无法检测高低电平,无法输出高低电平,无法进入外部中断等问题。
#include "H/Function_Init.H"
/*****************************************************
*函数名称:void IO_Init(void)
*函数功能:IO初始化
*入口参数:void
*出口参数:void
*****************************************************/
void IO_Init(void)
{
#if (IC_MODEL == SC92F73A3) //SC92F73A3脚定义
P0CON = 0x00; //设置P0为高阻输入模式
P0PH = 0x00;
P1CON = 0x00; //设置P1为高阻带上拉模式
P1PH = 0xFF;
P2CON = 0xFF; //设置P2为强推挽模式
P2PH = 0x00;
P5CON = 0xFF; //设置P4为强推挽模式
P5PH = 0x00;
#endif
#if (IC_MODEL == SC92F73A2) //SC92F73A2脚定义
P0CON = 0x00; //设置P0为高阻输入模式
P0PH = 0x00;
P1CON = 0x00; //设置P1为高阻带上拉模式
P1PH = 0xFF;
P2CON = 0xFF; //设置P2为强推挽模式
P2PH = 0x00;
SC92F73A2_NIO_Init(); //未引出IO口配置
#endif
#if (IC_MODEL == SC92F73A1) //SC92F73A1脚定义
P0CON = 0x00; //设置P0为高阻输入模式
P0PH = 0x00;
P1CON = 0x00; //设置P1为高阻带上拉模式
P1PH = 0xFF;
P2CON = 0xFF; //设置P2为强推挽模式
P2PH = 0x00;
SC92F73A1_NIO_Init(); //未引出IO口配置
#endif
}
2、外部中断初始化(配置IE、IP、INTxF、INTxR)
IE = 0xFF;//二进制11111111,表示EA=1 中断使能总控制打开,EADC=1 ADC转换完成时产生中断,ET2=1 允许TIMER2中断,EUART=1 允许UART中断,ET1=1 允许TIMER1中断,EINT1=1 允许外部中断1中断,ET0=1 允许TIMER0中断,EINT0=1 允许外部中断0中断。
IP=0xB8;//二进制10111000,表示IPT2=1 TIMER2优先级高,IPUART=1 UART优先高,IPT1=1 TIMER1优先级高。
INT0F = 0x02;//二进制00000010,表示INT0F1=1 INT0的通道1外部下降沿中断使能使用对应中断函数void EX0() interrupt 1{}
#include "H/Function_Init.H"
void EX_Init(void);
uchar INT1_flag = 0x00;
/*****************************************************
*函数名称:void EXTI_Test(void)
*函数功能:外部中断测试
*入口参数:void
*出口参数:void
*****************************************************/
void EXTI_Test(void)
{
EX_Init();
while(1)
{
}
}
/*****************************************************
*函数名称:void EX_Init(void)
*函数功能:外部中断初始化
*入口参数:void
*出口参数:void
*****************************************************/
void EX_Init(void)
{
//配置中断口INT03(P13)、INT12/13(P16/17)、INT24/25(P20/21)
P1CON &= 0X37; //中断IO口设置为高阻输入
P1PH |= 0xC8; //中断IO口设置为高阻带上拉
P2CON &= 0XFC; //中断IO口设置为高阻输入
P2PH |= 0x03; //中断IO口设置为高阻带上拉
//配置INT03上升沿中断、INT12/13下降沿中断、INT24/25双沿中断
//下降沿设置
INT0F = 0X00 ; //xxxx 0000 0关闭 1使能
INT1F = 0X0C ; //xxxx xxxx 0关闭 1使能
INT2F = 0X30 ; //0000 xxxx 0关闭 1使能
//上升沿设置
INT0R = 0X08 ; //xxxx 0000 0关闭 1使能
INT1R = 0X00 ; //xxxx xxxx 0关闭 1使能
INT2R = 0X30 ; //0000 xxxx 0关闭 1使能
//外部中断优先级设置
IE |= 0x05; //0000 0x0x
IE1 |= 0x08; //0000 x000 INT2使能
IP |= 0X00;
IP1 |= 0X00;
EA = 1;
}
/*****************************************************
*函数名称:void EX0/1/2() interrupt 0/2/10
*函数功能:外部中断函数
*入口参数:void
*出口参数:void
*****************************************************/
void EX0() interrupt 0
{
P24 = ~P24;
}
void EX1() interrupt 2
{
P25= ~P25;
if(P16 == 0)
{
INT1_flag = 0x10; //INT12产生中断
}
if(P17 == 0)
{
INT1_flag = 0x20; //INT13产生中断
}
}
void EX2() interrupt 10
{
P26 = ~P26;
}
3、定时器初始化(配置TMCON、TCON、TMOD、THx、TLx)
fsys系统频率可在烧录器配套软件窗口选择频率,主要为MCU内部RC振荡器分频。
#include "H/Function_Init.H"
void Timer_Init(void);
/*****************************************************
*函数名称:void Timer_Test(void);
*函数功能:T0/T1/T2测试
*入口参数:void
*出口参数:void
*****************************************************/
void Timer_Test(void)
{
Timer_Init();
while(1)
{
}
}
/*****************************************************
*函数名称:void Timer_Init(void)
*函数功能:T0/T1/T2初始化
*入口参数:void
*出口参数:void
*****************************************************/
void Timer_Init(void)
{
TMCON = 0X07; //------111 ;Timer0、Tiemr1和Tiemr2选择时钟Fsys
//T0设置
TMOD |= 0x01; //0000 0001;Timer0设置工作方式1
TL0 = (65536 - 16000)%256; //溢出时间:时钟为Fsys,则16000*(1/Fsys);
TH0 = (65536 - 16000)/256;
TR0 = 0;
ET0 = 1;//定时器0允许
TR0 = 1;//打开定时器0
//T1设置
TMOD |= 0x20; //0010 0000;Timer1设置工作方式2
TL1 = 256 - 160; //溢出时间:时钟为Fsys,则160*(1/Fsys);
TH1 = 256 - 160;
TR1 = 0;
ET1 = 1;//定时器1允许
TR1 = 1;//打开定时器1
//T2设置
T2MOD = 0x00;
T2CON = 0x00; //设置为16位重载寄存器
RCAP2H = (65536-32000)/256; //溢出时间:时钟为Fsys,则32000*(1/Fsys);
RCAP2L = (65536-32000)%256;
TR2 = 0;
ET2 = 1;//定时器2允许
TR2 = 1;//打开定时器2
/*
//Timer2捕获功能
T2CON = 0X09; //使能EXT2,16位捕获模式
T2MOD = 0X00;
TH2 = 0X00;
TL2 = 0X00;
RCAP2H = 0X00;
RCAP2L = 0X00;
TR2 = 0;
ET2 = 1;//定时器2允许
TR2 = 1;//打开定时器2
*/
EA = 1;
}
/**************************************************
*函数名称:void timer0/1/2() interrupt 1/3/5
*函数功能:定时器中断产生方波
*入口参数:void
*出口参数:void
**************************************************/
void timer0() interrupt 1
{
TL0 = (65536 - 16000)%256;
TH0 = (65536 - 16000)/256;
P24 = ~P24;
}
void timer1() interrupt 3
{
P25 = ~P25;
}
void Timer2Int(void) interrupt 5
{
TF2 = 0; //溢出清零
P26 = ~P26;
}
4、ADC初始化(配置ADCCON、ADCCFG0、ADCCFG1、ADCCFG2)
#include "H/Function_Init.H"
void ADC_Init(uint Channel,uchar ADCFreq);
unsigned int ADCValue = 0x0000;
bit AdcFlag = 0;
/***********ADC采样频率选择*************/
enum ADCFreq {F32=0,F24,F16,F12,F8,F6,F4,F3};
/***********ADC采样口选择*************/
#if (IC_MODEL == SC92F73A3)
enum Channel {AIN0=0,AIN1,AIN2,AIN3,AIN4,AIN5,AIN6,AIN7,AIN8,AIN9,VDD4=31};
#endif
#if (IC_MODEL == SC92F73A2)
enum Channel {AIN2=2,AIN3,AIN4,AIN5,AIN8=8,AIN9,VDD4=31};
#endif
#if (IC_MODEL == SC92F73A1)
enum Channel {AIN3=3,AIN4,AIN8=8,AIN9,VDD4=31};
#endif
/*****************************************************
*函数名称:void ADC_Test(void)
*函数功能:ADC测试
*入口参数:void
*出口参数:void
*****************************************************/
void ADC_Test(void)
{
ADC_Init(AIN3,F8);
while(1)
{
ADCCON |= 0X40; //开始ADC转换
while(!AdcFlag); //等待 ADC转换完成;
AdcFlag = 0;
ADCValue=(ADCVH<<4)+(ADCVL>>4);
}
}
/*****************************************************
*函数名称:void ADC_Init(uint Channel,uchar ADCFreq)
*函数功能:ADC初始化
*入口参数:void
*出口参数:void
*****************************************************/
void ADC_Init(uint Channel,uchar ADCFreq)
{
ADCCON = 0X80|Channel; //开启ADC,ADC采样频率为2M ,选择Channel位ADC采样口
if(Channel<8)
{
ADCCFG0 = 1< } else { ADCCFG1 = 1<<(Channel-8); //设置Channel作为采样口 } ADCCFG2 = ADCFreq; IE |= 0X40; //开启ADC中断 EA = 1; } void ADC_Interrupt(void) interrupt 6 { ADCCON&=~(0X20); //清中断标志位 AdcFlag = 1; } 5、PWM初始化(配置PWMCFG、PWMCON、PWMPRD、PWMDTYx) #include "H/Function_Init.H" void PWM_Init(void); /***************************************************** *函数名称:void PWM_Test(void) *函数功能:PWM测试 *入口参数:void *出口参数:void *****************************************************/ void PWM_Test(void) { PWM_Init(); while(1) { } } /***************************************************** *函数名称:void PWM_Init(void) *函数功能:PWM初始化 *入口参数:void *出口参数:void *注意:周期与占空比的低2位要先写值,再写高8位 *****************************************************/ void PWM_Init(void) { PWMCFG = 0x00; //设置PWM系统时钟,控制输出反向 PWMCON = 0X3f; //控制是否输出到IO口 PWMDTYA = 0xea; //周期与PWM0/1/2占空比的低2位设置 PWMPRD = 0x4f; //周期高8位设置 PWMDTY0 = 0x28; //PWM0占空比高8位设置 PWMDTY1 = 0x28; //PWM1占空比高8位设置 PWMDTY2 = 0x28; //PWM2占空比高8位设置 PWMDTYB = 0X00; //PWM3/4/5周期与占空比的低2位设置 PWMDTY3 = 0X14; //PWM3占空比高8位设置 PWMDTY4 = 0X14; //PWM4占空比高8位设置 PWMDTY5 = 0X14; //PWM5占空比高8位设置 PWMCON |= 0x80; //打开PWM使能端 IE1 |= 0x02; EA = 1; } /* void PWM_Dead(void) //死区设置 { PWMCFG = 0X38; //设置PWM系统时钟,控制输出反向 PWMCON = 0X3F; //控制是否输出到IO口 PWMDTYB |= 0X80; //设置死区模式 PWMPRD = 0X18; //周期高8位设置 PWMDTYA = 0XEA; //11 10 10 10 周期与占空比低2位 PWMPRD = 0X18; //周期与PWM0/1/2占空比的低2位设置 PWMDTY0 = 0X0C; //PWM0占空比高8位设置 PWMDTY1 = 0X10; //PWM1占空比高8位设置 PWMDTY2 = 0X0C; //PWM2占空比高8位设置 PWMDTY3 = 0X00; //死区时间设置 PWMCON |= 0X80; //开PWM } */ void PWMInt(void) interrupt 8 { P00=~P00; } 6、内部IAP(EEPROM)使用 #define IapROM 0x00 #define IapEPPROM 0x02 IAPWrite(0x7F,Date_num,IapEPPROM);//存入的数据Date_num Date=IAPRead(0x7F,IapEPPROM);//读取数据Date IAPWrite、IAPRead不要频繁操作,只有<=10万次写入操作。 #include "H/IAP_Init.H" unsigned char code *IapAddr = 0x00; void IAPWrite(uint Addr,INT8S Value,uchar IAPArea); INT8S IAPRead(uint Addr,uchar IAPArea); uchar IapReadData = 0x00;//存放读取的IAP数据 /***************************************************** *函数名称:void IAPWrite(uchar Addr,uchar Value,uchar IAPArea) *函数功能:IAP写初始化 *入口参数:Addr,Value,IAPArea *出口参数:void *****************************************************/ void IAPWrite(uint Addr,INT8S Value,uchar IAPArea) { EA = 0; IAPDAT = Value;//写入数据Data IAPADH = ((Addr>>8)&0X7F);//写入地址的高5位 IAPADL = Addr;//写入地址的低8位 IAPADE = IAPArea;//IAPArea=0x00:选择ROM区操作 IAPArea=0x02:选择EEPROM区操作 IAPKEY = 240;//IAP开启保护控制时间 IAPCTL = 0x06;//CPU hold time为2ms,写入操作命令 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); IAPADE = 0x00;//MOVC指向ROM EA = 1; } /***************************************************** *函数名称:uchar IAPRead(uchar Addr,uchar IAPArea) *函数功能:IAP读初始化 *入口参数:Addr,IAPArea *出口参数:ReadValue *****************************************************/ INT8S IAPRead(uint Addr,uchar IAPArea) { uchar ReadValue = 0x00; EA = 0; IAPADE = IAPArea; ReadValue = *(IapAddr+Addr);//读取的数据 IAPADE = 0x00;//MOVC指向ROM EA = 1; return ReadValue; } 好文推荐
发表评论