STC12C5A60S2单片机的总结
STC12C5A60S2单片机的总结
文章目录
- STC12C5A60S2单片机的总结
- 引言:
- 1.独立串口
- 1.1 相关寄存器
- 1.2 实验程序
- 2.内置看门狗
- 2.1 看门狗寄存器
- 2.2 实验程序:
- 3. EEPROM
- 3.1 相关的寄存器
- 3.2 实验程序
- 4.内置ADC
- 4.1 相关的寄存器
- 4.2 实验程序
- 5. PCA定时器做软件定时的功能
- 5.1 相关的寄存器
- 5.2 实验程序
- 6. PCA定时器做PWM输出的功能(一路输出)
- 6.1 相关寄存器
- 6.2 实验程序
- 7. PCA定时器做PWM输出的功能(两路输出)
- 8. PCA定时器用于扩展外部中断
- 9. PCA定时器用于输入捕获
- 10. PCA定时器用于生成高速脉冲
引言:
STC12C5A60S2系列主要性能:
- 高速: 1个时钟/机器周期,增型8051内核,速度比普通8051快6~12倍
- 宽电压: 5.5~4.0V, 2.1~3.6V( STC12LE5A60S2系列)
- 增加第二复位功能脚/P4.6(高可靠复位, 可调整复位门槛电压,频率
SCON=0X50;
BRT=0Xfd; //一定要11.0592M晶振,BRT的值即为用定时器做波特率发生器方式的定时器匹配值; 9600波特率
AUXR=0x11;
ES=1;
EA=1;
}
void UART_SendData(uchar dat)
{
SBUF=dat;
while(TI==0);
TI=0;
}
void main()
{
ck_init();
while(1)
{
if(flag==1)
{
ES=0; //关串口中断
flag=0;
SBUF=a;
UART_SendData(a+0x30);
ES=1;
}
}
}
void serial() interrupt 4
{
flag=1;
if(SBUF==0x01)
{
led1=0;
}
else led1=1;
a=SBUF;
RI=0;
}
uint x,y;
for(x=t;x0;x--)
for(y=920;y>0;y--);
}
void main()
{
WDT_CONTR=wdt_reset_counts;
p20=0;
delayms(500);
p20=1;
while(1)
{
delayms(5000); // 延时超过看门狗超时时间单片机会复位,p2.0口led不停闪烁
WDT_CONTR=wdt_reset_counts;
}
}
3. EEPROM
STC12C5A60S2系列单片机内部集成了的EEPROM是与程序空间是分开的,利用ISP/IAP技术可将内部Data Flash当EEPROM,擦写次数在10万次以上。EEPROM可分为若干个扇区,每个扇区包含512字节。使用时,建议同一次修改的数据放在同一个扇区,不是同一次修改的数据放在不同的扇区,不一定要用满。数据存储器的擦除操作是按扇区进行的。
3.1 相关的寄存器
底层寄存器的操作可以自行看单片机的官方手册,对于使用12单片机的EEPROM,只需要会调用EEPROM模块的API即可。
STC12C5A60S2单片机的EEPROM资源(每个扇区512字节):
3.2 实验程序
#include"stc12c5a60s2.h" typedef unsigned int uint; typedef unsigned char uchar; #include"lcd.h" #define EEP_address 0x0000 uchar code ASCII[] = {'0','1','2','3','4','5','6','7','8','9'}; uchar a,ge,shi; uchar TestCnt; uchar zf[]="num:"; uchar shu; void EEPROM_read_n(uint EE_address,uchar *DataAddress,uchar lenth); void EEPROM_SectorErase(uint EE_address); void EEPROM_write_n(uint EE_address,uchar *DataAddress,uchar lenth); void delayms(uint t) { uint x,y; for(x=t;x>0;x--) for(y=920;y>0;y--); } void main() { LcdInit(); delayms(5); EEPROM_read_n(EEP_address,&TestCnt,1); //读出保存值 读N个字节函数 最多255字节一次 TestCnt++; if(TestCnt>100) TestCnt=0; // 如果开机次数大于100,清零 EEPROM_SectorErase(EEP_address); //扇区擦除函数,写入之前必须清楚扇区 EEPROM_write_n(EEP_address,&TestCnt,1); //写1个字节函数 最多255字节一次。把开机次数写入EEPROM中 shi=TestCnt/10;ge=TestCnt%10; // 显示开机次数 LcdWriteCom(0x80); for(shu=0;shu LcdWriteData(zf[shu]); } while(1) { LcdWriteCom(0x05+0x80);LcdWriteData(ASCII[shi]); LcdWriteCom(0x06+0x80);LcdWriteData(ASCII[ge]); } } uint j; PrintString("****** STC12C5A60S2系列ADC程序 2011-02-27 ******\r\n"); //上电后串口发送一条提示信息 P1ASF = (1 delay_ms(250); delay_ms(250); delay_ms(250); delay_ms(250); j = adc10_start(0); // P1.0 ADC Tx1Send('A'); Tx1Send('D'); Tx1Send('0'); Tx1Send('='); Tx1Send(j/1000 + '0'); Tx1Send(j%1000/100 + '0'); Tx1Send(j%100/10 + '0'); Tx1Send(j%10 + '0'); Tx1Send(0x0d); Tx1Send(0x0a); } } /********************* 做一次ADC转换 *******************/ uint adc10_start(uchar channel) //channel = 0~7 { uint adc; uchar i; ADC_RES = 0; ADC_RESL = 0; ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel; // for(i=0; i if(ADC_CONTR & ADC_FLAG) { ADC_CONTR &= ~ADC_FLAG; // adc = 0; // adc = (ADC_RES unsigned int i; do{ i = MAIN_Fosc / 14000; while(--i) ; //14T per loop }while(--ms); } /********************** 模拟串口相关函数************************/ void BitTime(void) //位时间函数 { uint i; i = ((MAIN_Fosc / 100) * 104) / 140000L - 1; //根据主时钟来计算位时间 while(--i); } //模拟串口发送 void Tx1Send(uchar dat) //9600,N,8,1 发送一个字节 { uchar i; EA = 0; P_TXD1 = 0; BitTime(); for(i=0; i if(dat & 1) P_TXD1 = 1; else P_TXD1 = 0; dat = 1; BitTime(); } P_TXD1 = 1; EA = 1; BitTime(); BitTime(); } void PrintString(unsigned char code *puts) //发送一串字符串 { for (; *puts != 0; puts++) Tx1Send(*puts); //遇到停止符0结束 } uint j; PrintString("****** STC12C5A60S2系列ADC程序 2011-02-27 ******\r\n"); //上电后串口发送一条提示信息 P1ASF = (1 delay_ms(250); delay_ms(250); delay_ms(250); delay_ms(250); ADC_RES = 0; ADC_RESL = 0; B_ADC_OK = 0; ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | ADC_CH0; while(!B_ADC_OK); //等待ADC完成 j = adc; Tx1Send('A'); Tx1Send('D'); Tx1Send('0'); Tx1Send('='); Tx1Send(j/1000 + '0'); Tx1Send(j%1000/100 + '0'); Tx1Send(j%100/10 + '0'); Tx1Send(j%10 + '0'); Tx1Send(0x0d); Tx1Send(0x0a); } } /********************* ADC转换中断 *******************/ void adc_interrupt(void) interrupt 5 //channel = 0~7 { ADC_CONTR &= ~ADC_FLAG; //clear ADC flag adc = (uint)ADC_RES; adc = (adc unsigned int i; do{ i = MAIN_Fosc / 14000; while(--i) ; //14T per loop }while(--ms); } /********************** 模拟串口相关函数************************/ void BitTime(void) //位时间函数 { uint i; i = ((MAIN_Fosc / 100) * 104) / 140000L - 1; //根据主时钟来计算位时间 while(--i); } //模拟串口发送 void Tx1Send(uchar dat) //9600,N,8,1 发送一个字节 { uchar i; P_TXD1 = 0; BitTime(); for(i=0; i if(dat & 1) P_TXD1 = 1; else P_TXD1 = 0; dat = 1; BitTime(); } P_TXD1 = 1; BitTime(); BitTime(); } void PrintString(unsigned char code *puts) //发送一串字符串 { for (; *puts != 0; puts++) Tx1Send(*puts); //遇到停止符0结束 } CCF0=0; //中断标志位清0 CCAP0L=value; //比较寄存器程序赋值(比上次加1倍) CCAP0H=value8; value=value+t100hz; // value一直增加不会溢出??会CL、CH也会溢出。溢出后的数值会丢弃二进制中超过最高位的 if(cnt--==0) //1s t100hz=0.01s 0.01*100=1s { cnt=100; p20=~p20; } } void main() { CCON=0; //cf cr ccf1 ccf0为0 CL=0; //pca计数值初始为0 CH=0; CMOD=0X00; //CIDL=0、SYSclk/12、ECF = 0 value=t100hz; //0.01s CCAP0L=value; //给比较寄存器赋值 CCAP0H=value8; value=value+t100hz; //value加一倍 CCAPM0=0x49; //ecmo0 mat0 eccf0为1;ECOM0= 1时,允许比较器功能;匹配将置位CCON寄存;使能CCF0中 CR=1; //起动 PCA计数器阵列计数,CCON寄存器的一位 EA=1; cnt=0; while(1) { } } CCON=0; //CF(pca计数溢出标志) CR(是否启动pca计数) CCF1、CCF0(pca模块中断标志) 全清0 CL=0; //pca计数值 只有CL计数 8位 CH=0; //CH不计数 CMOD=0X02; //选择pca/pwm时钟频率(决定了输出pwm波的频率) 是否中断 CCAP0H=CCAP0L=0X80; //pwm输出通道0(CCP0) 50%占空比 CL与之比较 CCAPM0=0X42; //ecom0 pwm0 置1(使能pwm通道0) CCAP1H=CCAP1L=0XFF; //pwm输出通道0(CCP1) 0占空比 CL与之比较 PCA_PWM1=0X03; //固定输出0 CCAPM1=0X42; //ecom1 pwm1 置1(使能pwm通道1) CR=1; //启动pca定时器 while(1) { } } unsigned char i, j; _nop_(); _nop_(); i = 108; j = 144; do { while (--j); } while (--i); } void pwm_kz() { if(pwm0255) pwm0=0; if(pwm1255) pwm1=0; } void main(void) { uint i; //AUXR1 |= (1 for(i=0;i pwm0++; pwm1++; pwm_kz(); CCAP0H = pwm0; //set PWM wide CCAP1H = pwm1; //set PWM wide Delay10ms(); } } } if(CCF0==1) { CCF0=0; p10=~p10; } } void main() { CCON=0; //CF(pca计数溢出标志) CR(是否启动pca计数) CCF1、CCF0(pca模块中断标志) 全清0 CL=CH=0; //pca计数值 CMOD=0X00; //选择pca/pwm时钟频率(决定了输出pwm波的频率) 是否中断 CCAPM0=0X11; //下降沿捕获 //CCAPM0=0X21; //上升沿捕获 //CCAPM0=0X21; //下降、上升都捕获 CR=1; //启动pca定时器 EA=1; //开启总中断 while(1) { } } Tx1Send('P'); Tx1Send('C'); Tx1Send('A'); Tx1Send(id + '0'); Tx1Send('='); Tx1Send(dat/10000 + '0'); Tx1Send(dat%10000/1000 + '0'); Tx1Send(dat%1000/100 + '0'); Tx1Send(dat%100/10 + '0'); Tx1Send(dat%10 + '0'); Tx1Send(0x0d); Tx1Send(0x0a); } /********************* 主函数 *************************/ void main(void) { CCAPM0 = 0x11; //CCAP0下降沿捕捉,允许中断 下降沿捕捉: 0x11, 上升沿捕捉: 0x21, 上升下降沿捕捉: 0x31 CCAPM1 = 0x11; //CCAP1下降沿捕捉,允许中断 下降沿捕捉: 0x11, 上升沿捕捉: 0x21, 上升下降沿捕捉: 0x31 CMOD = (PCA_IDLE_DISABLE if(B_Cap0) { B_Cap0 = 0; tx(0, CCAP0_tmp - CCAP0_Last); CCAP0_Last = CCAP0_tmp; //为什么要减去上次值,CL和CH没有清零 } if(B_Cap1) { B_Cap1 = 0; tx(1, CCAP1_tmp - CCAP1_Last); CCAP1_Last = CCAP1_tmp; } } } //======================================================================== // 函数: void PCA_interrupt (void) interrupt 7 // 描述: PCA中断服务程序。 // 参数: 无。 // 返回: 无。 // 版本: VER1.0 // 日期: 2009-12-30 // 备注: //======================================================================== void PCA_interrupt (void) interrupt 7 { if(CCF0 == 1) //PCA模块0中断 { CCF0 = 0; //清PCA模块0中断标志 CCAP0_tmp = CCAP0H; //读CCAP0H (CH CL值会自动装载到CCAP0H CCAP0L) CCAP0_tmp = (CCAP0_tmp CCF1 = 0; //清PCA模块1中断标志 CCAP1_tmp = CCAP1H; //读CCAP0H CCAP1_tmp = (CCAP1_tmp CF = 0; //清PCA溢出中断标志 P10 = ~P10; //14HZ at 22.1184MHZ } } /********************** 模拟串口相关函数************************/ void BitTime(void) //位时间函数 { uint i; i = ((MAIN_Fosc / 100) * 104) / 140000L - 1; //根据主时钟来计算位时间 while(--i); } //模拟串口发送 void Tx1Send(uchar dat) //9600,N,8,1 发送一个字节 { uchar i; P_TXD1 = 0; BitTime(); for(i=0; i if(dat & 1) P_TXD1 = 1; else P_TXD1 = 0; dat = 1; BitTime(); } P_TXD1 = 1; BitTime(); BitTime(); } void PrintString(unsigned char code *puts) //发送一串字符串 { for (; *puts != 0; puts++) Tx1Send(*puts); //遇到停止符0结束 } PWMn_init(); //初始化PCA while(1) { } } //======================================================================== // 函数: void PWMn_init(void) // 描述: 初始化程序。 // 参数: 无。 // 返回: 无。 // 版本: VER1.0 // 日期: 2009-12-30 // 备注: //======================================================================== void PWMn_init(void) { #ifdef STC12C5201AD P3M1 &= ~0xA0, P3M0 |= 0xA0; //CCAP0、CCAP1使用PUSH-PULL输出模式,STC12C5201AD系列。 #else P1M1 &= ~0x18, P1M0 |= 0x18; //CCAP0、CCAP1使用PUSH-PULL输出模式,STC12C5A60S2系列。 #endif CCON = 0; //清除CF、CR、CCF0、CCF1 IPH |= 0x80; //PCA中断使用最高优先级 PPCA = 1; CMOD = (PCA_IDLE_DISABLE if(CCF0 == 1) //PCA模块0中断 { CCF0 = 0; //清PCA模块0中断标志 CCAP0_tmp +=2765 ; //1KHZ at 11.0592M 2765 CCAP0L = CCAP0_tmp%256; //将影射寄存器写入捕获寄存器,先写CCAP0L (自己改的是对的!!!!!) CCAP0H = CCAP0_tmp/256; //后写CCAP0H } if(CCF1 == 1) //PCA模块1中断 { CCF1 = 0; //清PCA模块1中断标志 CCAP1_tmp +=28; //2KHZ at 22.1184MHZ 5530 11.0592M 28 (这里例程是错的!!,自己计算的28) CCAP1L = (unsigned char)CCAP1_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L CCAP1H = (unsigned char)(CCAP1_tmp 8); //后写CCAP0H } if(CF == 1) //PCA溢出中断 { CF = 0; //清PCA溢出中断标志 P10 = ~P10; //168.75HZ at 22.1184MHZ } }
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!



