作者

QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118

参考

51单片机实现scanf和printf函数
通过串口实现printf和scanf函数
适用于单片机的小型类shell的命令行软件

目标

如何从头开始一个单片机项目,结合STC8A来说一说我的做法,因为这也是我第一次使用STC8A这个芯片,我这里不想谈什么面向对象设计,什么代码解耦和,什么代码复用,小项目,一期项目搞完,后期修修补补也够了,改几行代码搞定,拿到项目说明,首先总结一下用到的所有外设,打好工程的基本框架,比如,

app是应用,hw是用到的外设驱动,util是工具类代码,app将调用hw驱动和util工具来完成项目功能,我这里不强调代码复用,所以来了一个新项目,hw下的代码都要看情况小改,这点肯定比不过STM32那种函数库,不过这种方式软件效率必然是最高的,强调通用性也就必然会损失性能。在这个项目里,

  • main.c是主函数
  • shellcmd.c是调试命令函数
  • adc.c是模拟数据采集,电压和温度
  • iap.c是操作STC8A内部EEPROM
  • pin.c是IO控制,在main函数开始初始化所有管脚状态,包括设置管脚是uart,spi等特殊功能管脚
  • pwm.c是STC8A内部高性能PWM模块控制代码,驱动电机或者蜂鸣器等
  • timer.c是STC8A定时器控制代码,定时器可提供时间基准,完成延时和任务切换
  • uart.c是串口函数
  • disp.c是液晶屏显示函数
  • key.c是键盘扫描函数
  • pca.c是PCA模块控制代码,测量外部信号频率
  • shell.c是调试终端工具,配合uart使用

根据项目需求,完成驱动设计,比如在adc.c中完成15路adc采集,pwm.c中完成2路pwm控制,下面介绍我的开发,

ADC

初始化函数adcInit配置管脚P1.0~7 P0.0~6为ADC模式,配置速度模式为512个CPU时钟,这也是最慢的速度,配置采样数据模式为左对齐,左对齐的目的是将12位精度的ADC当成8位用,最后将将ADC电源打开,ADCCFG = 0x0f时ADC将采用最慢的速度采集,由于没加入RTOS,这会卡住很长的时间,注意场合。

void PinInit(void)
{/*P1.0~7 ADC0~7 P0.0~6 ADC8~14 P0.7 push-pull out*/P1M0 = 0x00;P1M1 = 0xff;P0M0 = 0x80;P0M1 = 0x7f;
}
void adcInit()
{ADCCFG = 0x0f;                              ADC_CONTR = 0x80;
}

获取每个通道的电压,

unsigned char adcGetCh(unsigned char ch)
{unsigned char c;ADC_CONTR |= (0x40 + ch);_nop_();_nop_();while (!(ADC_CONTR & 0x20));ADC_CONTR &= ~0x20;c = ADC_RES;return c;
}

PWM

初始化PWM,没有使用任何PWM中断,相应位置0,通道初始电平为0,第一个反转点为0,则PWM波从高开始,24MHz的系统时钟,周期计数为240,产生100KHz的PWM波,访问PWM寄存器需要控制P_SW2的EAXFR位,

#include "config.h"
#include "stc8.h"
#include <intrins.h>
#include "pwm.h"
/*
PWM0, P20, 1Hz, %50, beep
PWM6, P26, 100KHz, control by P00/P01, fixed-power
PWM7, P27, 100KHz, control by P00/P01, fixed-current
*/
void PwmInit(void)
{/*EAXFR=1 when reg addr>0xFFF0*/P_SW2 |= 0x80;PWMCKS = 0x00;//system clk FOSC=24MHzPWMC = 240;//100KHz PWM6T1= 0;PWM6T2= 120;PWM6CR= 0x80;PWM7T1= 0;PWM7T2= 120;PWM7CR= 0x80;P_SW2 &= 0x7f;PWMCR = 0x80;
}

强制输出高或低,很多场景下会用到,

/*
force high/low
*/
void PwmSetPin(unsigned char ch, unsigned char out)
{if (out)(*(unsigned char volatile xdata *)(0xff05 + ch << 0x10)) = 0x2;else(*(unsigned char volatile xdata *)(0xff05 + ch << 0x10)) = 0x1;
}

PCA

初始化PCA在P2口,

  /*Uart1 P30 P31 CCP P22~P26*/P_SW1 = 0x1f;

初始化PCA为外部脉冲捕获功能,CCP0为P23,CCP1为P24,CCP2为P25,上升沿捕获,这样两个上升沿之间的宽度就是周期,可计算出频率,

void PcaInit(void)
{/*clear interrupt flag*/CCON = 0x00;/*system clk enable overflow interrupt*/CMOD = 0x09;CL = 0x00;CH = 0x00;/*capture on rising edge*/CCAPM0 = 0x21;CCAP0L = 0x00;CCAP0H = 0x00;CCAPM1 = 0x21;CCAP1L = 0x00;CCAP1H = 0x00;CCAPM2 = 0x21;CCAP2L = 0x00;CCAP2H = 0x00;/*start*/CR = 1;
}

中断处理,计数器只有16位,对于50Hz这样的波形,24MHz系统时钟,会发生溢出,通过检测CF溢出中断才能正确计算频率,其中ccpCfCnt也需要定期清零,否则仍然有溢出风险,

void PCA_Isr() interrupt 7
{if (CF){CF = 0;ccpCfCnt++;                                  }for (ccpi = 0; ccpi < CCP_NUM; ccpi++) {if (CCON & (1 << ccpi)) {CCON &= (1 << ccpi);ccpCount0[i] = ccpCount1[i];ccpCount1[i] = (ccpCfCnt << 16) + (CCAP0H << 8) + CCAP0L;ccpTick[i] = ccpCount1[i] - ccpCount0[i];/*if (ccpCount1[i] > ccpCount0[i])ccpTick[i] = ccpCount1[i] - ccpCount0[i];else {ccpCfCnt = 0;ccpCount0[i] = 0;ccpCount1[i] = (ccpCfCnt << 16) + (CCAP0H << 8) + CCAP0L;}*/}}
}

Timer

定时器用来调度任务,没有RTOS,没有任务的时候,CPU可以进入低功耗状态,定时器默认工作在12T模式,即计数时钟是CPU时钟的1/12,sysTick存储当前时刻的开机时间,在溢出的时候累加,单位毫秒,最大为49.7天,之后就溢出了,需要注意,定时器工作在模式0,16位自动重载模式,T0_CNTS计算法则是控制定时器距离溢出的时间为10ms,

/*overflow time 10ms*/
#define T0_OF_TIME      10
#define T0_CNTS         (65536 - ((FOSC / 12) * 10) / 1000)
unsigned long sysTickMs;void Timer0Isr() interrupt 1
{sysTickMs += T0_OF_TIME;
}void Timer0Init(void)
{sysTickMs = 0;/*16-bit auto reload*/TMOD = 0x00;TL0 = T0_CNTS;TH0 = (T0_CNTS >> 8);/*start T0*/TR0 = 1;/*IE enable T0 overflow interrupt*/ET0 = 1;
}

LVD低压检测

本打算在低压检测时存储掉电数据,后发现EEPROM总是丢数,坑啊

void LvdIsr() interrupt 6
{PCON &= ~LVDF;     IapSave();
}

STC8A单片机应用开发相关推荐

  1. STC8A单片机使用RTOS

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 参考 Small RTOS51 ...

  2. 《51单片机应用开发从入门到精通》——2.2 跑马灯实例

    本节书摘来自异步社区<51单片机应用开发从入门到精通>一书中的第2章,第2.2节,作者 张华杰,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.2 跑马灯实例 ...

  3. 《51单片机应用开发从入门到精通》——2.6 中断控制功能的作用

    本节书摘来自异步社区<51单片机应用开发从入门到精通>一书中的第2章,第2.6节,作者 张华杰,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.6 中断控制功 ...

  4. 《51单片机应用开发范例大全(第3版)》——第1章 单片机C语言开发基础

    本节书摘来异步社区<51单片机应用开发范例大全(第3版)>一书中的第1章,作者:张杰 , 宋戈 , 黄鹤松 , 员玉良,更多章节内容可以访问云栖社区"异步社区"公众号查 ...

  5. 单片机广告灯实验总结_温州很强的ly51s单片机程序开发公司

    温州很强的ly51s单片机程序开发公司 sdthfsfd 温州很强的ly51s单片机程序开发公司 "时,表示波特率自适应工作正确完成,如图所示,可以进行参数设置和校准操作.这也是为什么晶振的 ...

  6. 单片机单口不可用或被占用_昆明工业控制单片机应用开发价格

    昆明工业控制单片机应用开发价格 jwsndfc 昆明工业控制单片机应用开发价格结构图组成推挽结构,从理论上讲是可以通过调配管子的参数轻松实现输出大电流,带载能力,两个管子根据通断状态有四种不同的组合, ...

  7. PLC单片机实验开发设备

    在单片机的应用中,PLC控制系统已经成为了其组成中的重要组成部分.单片机主要利用PLC必备的编程接口来进行通信,使用LCD作为用户的界面,界面中可以显示出PLC的工作状态.工艺参数,也可以使用相应的按 ...

  8. EM78系列单片机的开发工具及编程器

    EM78单片机的开发工具一般包括:(1)宏汇编(交叉汇编)(2)仿真器(3)程序烧写器.单片机的开发过程如下: 1)    用编辑软件(如:EDIT.PE2等)输入源程序(扩展名DT) 2)    用 ...

  9. 如何快速开发便捷小风扇?泛海微单片机方案开发公司经验十足

    如何快速开发便捷小风扇?泛海微单片机方案开发公司经验十足近年来,便携小风扇是热销品,所以深受电子产品生产厂家的青睐.而想要快速生产便捷小风扇,选择一家支持小风扇单片机方案开发的实力企业就很关键了.那么 ...

最新文章

  1. 安装oracle并且小总结oracle sql
  2. jmeter如何定位网络延时_JMeter用户定义变量和properties变量高级使用
  3. Linux环境进程间通信(五): 共享内存(上)
  4. C语言:学生信息管理程序
  5. jdbc mysql 存储过程执行失败_JDBC连接执行MySQL存储过程报空指针或权限错误
  6. 数据库中union和union all的区别
  7. 硬盘容量统计显示WinDirStat v1.1.2.79(印心绿化版)
  8. s3c2440 IIC AT24C08
  9. python numpy安装教程_python 环境下安装 numpy
  10. 优秀关卡设计的十个原则
  11. echarts实现颜色渐变
  12. 数据结构——数组以及n维数组
  13. 使用xpath,正则表达式爬取豆瓣top250电影信息
  14. 通过百度账号获取个人信息
  15. Chrome添加扩展程序
  16. 基于STM32-F401的平衡小车
  17. Python 日志logging模块初探及多线程踩坑(2)
  18. word设置页码不在第一页开始;删除页眉横线的小技巧
  19. 思科模拟器 --- 三层交换机的基本配置
  20. TF-IDF算法加权

热门文章

  1. 【RPC】慕课网RPC教程
  2. 环保材料营造健康氛围
  3. 快速搭建个人博客——保姆级教程
  4. 怎么安装jdk6,怎么安装jdk-6u33-linux-i586.bin
  5. 国家食品药品监督管理局 前有27家网站有资格向个人销售非处方药
  6. WPF Prism框架
  7. 自动驾驶汽车?法律:伦理
  8. Hack The Box注册 —邀请码教学(含注册失败及解决步骤)
  9. 自动驾驶企业Mobileye估值坍塌:降至160亿美元 路演PPT曝光
  10. java stackoverflowerror与outofmemoryerror区别