|
随着社会形势的发展,顺职时学的摩托罗拉68由于仿真器贵、毕业出来自学的51芯片多时40脚或20脚且不带AD价格偏高、到用了段时间PIC发觉价格也很高……一次偶然的机会俾我现在瑞德发现了个他们自制的三星9454烧写器、又一次偶然的机会‘德记’向我推介了STM8。从始我的项目方案多了三星的9454与ST的STM8!
STM8属高配置中低价格型单片机、三星9454属低价型单片机。近排公司自己手头上没有什么事做,日头在公司研究9454,晚上在家睇STM8。经过两多个星期努力终于对9454的脾性摸透了(像庖丁解牛一样)。下面就让我将其例子及遇到问题发上来,作为引子。明天,回公司后继续对PWM、AD进行应用与测试(我想一理通百理明,定时中断会用了,其余也迎刃而解)
原问题点:1、不会设内外晶振(PIC可以烧写时设,但三星的由于资料小研究很耐才会)。具体用法见下面的程序注解。
2、不会用定时器产生中断(原来用IAR编的C,对于SYM的中断启动位付值起来不行。要用到:#define EI (__enable_interrupt()) //定义开中断标志))否则,芯片不能运行。
3、要用到上述语句,还要在程度开头包含如下语句:#include "intrinsics.h"//包含内部函数
4、在IAR上的需设置为:SAM8xRCRI
5、点Override default 且将输出文件改为:xx.hex
6、点Other Output
7、充分理解‘开漏输出’与‘推挽输出’的用法。与51的结构不一样,否则会有想不到的问题。
源程序:
#include <ioS3C9454.h>//
#include "iobit.h" //IO端口位操作定义文件
#include "intrinsics.h"//包含内部函数
//************************************************
//**此处为宏定义替换******
#define uchar unsigned char
#define uint unsigned int
#define EI (__enable_interrupt()) //定义开中断标志
#define DI (__disable_interrupt()) //定义关中断标志(这里是关键,因为IAR如果对SYM操作会有问题,所以只能这样开总中断)
__root const uchar DispTab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};
__root const uchar SmartOption[4]@0x3c={0x00,0x00,0xE4,0x03}; //0xE4=11100100 (第4位:0x00-外部晶振,0x01-外部RC,0x02-内部RC 0.5M,0x03-内部RC 3.3M)
static uint Ts; //125us
static uchar Tss;
static uchar Tsdisp;
static uchar SEC; //秒变量
static uchar MIN; //分变量
static uchar HOUR; //小时变量
static uchar ONE; //存放个位数据
static uchar TWO; //存放十位数据
static uchar THREE; //存放百位数据
static uchar FOUR; //存放千位数据
static uchar FIVE;
static uchar SIX;
static uchar SEVEN;
static uchar EIGHT;
void Ch (void); //初始化程序
void Time (void); //时间处理
void Disp (void); //数码管显示处理
void mDelay(void);
void TimeLed(void);
//主程序区====================================================================
void main(void)
{
Ch(); //第一次上电先对相关寄存器进行初始化
//=================================================================
//付初值区
Ts=0;
Tss=0;
Tsdisp=0;
SEC=0;
MIN=0;
HOUR=0;
P2=0xff;
P0=0xff;
//===================================================================
while(1)
{
Time (); //*时间处理子程序*/
//TimeLed(); //调用一个闪灯程序
}
}
//====================================================================
void Ch () //初始化程序
{
P0CONL=0xAA; //0xAA=10101010 P0.0~P0.4都设为推挽式输出
P1CON=0x0A; //0xFA=11111010 P1.1\1.0设为N沟开路输出 0xFA=00001010 P1.1\1.0设推挽式输出
P2CONL=0xAA; //0xAA=10101010 P2.0~2.3设为推挽输出
P2CONH=0x4A; //0x4a=01001010 P2.4~2.6设为推挽输出
BTCON=0xA4; //基本定时控制器 0xA4=1010 0100=1010-禁止看门狗 01-fosc/1024 0-没有作用 0-没有作用
CLKCON=0x18; //时钟控制寄存器 0x18=00011000= 11-时钟1分频
STOPCON = 0xA5;
//ADCON=0x8C;
//P0PND=0x08;
T0CON = 0x8A;//定时器设置 0x8A=11001010 11-fosc/8 00-- 1-清定时器 0-- 1-允许定时中断 0-清中断标志
T0DATA =45;//定时器初始值 0x64=100
EI; //开总中断(这里很重要,原来就是只用SYM寄存器,所以出理进不了中断)
}
//=====================================================================
void mDelay () //定时子程序
{ static uint temp;
static uint DelayTime;
DelayTime=1;
for(;DelayTime>0;DelayTime--)
{for(temp=0;temp<1500;temp++)
{;}
}
}
//=========================================================================
void TimeLed () //闪灯程序
{ static uchar i=0;
mDelay();
i++;
if(i==2)
{
i=0;
}
switch(i)
{case 0: P0=0xFF; break;
case 1: P0=0x00; break;
}
}
//============================================================================
/*时间处理子程序*/
void Time ()
{
if(SEC==60)
{SEC=0;
MIN++;
}
if(MIN==60)
{MIN=1;
HOUR++;
}
if(HOUR==13)
{HOUR=1;
}
ONE=SEC%10;
TWO=SEC/10;
if(TWO==0)
{TWO=10;} //十位消隐
THREE=MIN%10;
FOUR=MIN/10;
FIVE=HOUR%10;
SIX=HOUR/10;
}
//============================================================================
/*显示处理程序*/
void Disp ()
{
static uchar COUNT=0;
if(Tsdisp==15) //TS=125usX16=2ms
{
Tsdisp=0;
switch(COUNT) //端口用位操作
{
case 0: P2=DispTab[ONE] ,P1=0x01; break;
case 1: P2=DispTab[TWO] ,P1=0x02; break;
}
COUNT++;
if(COUNT==2)
{
COUNT=0;
}
}
}
//============================================================================
//*************************************************************************
//**中断向量及服务程序定义********
#pragma vector=0x00
__interrupt void int_9454()
{
T0CON=T0CON&0xFE; //中断服务程序完后清中断标志
Ts++; //定时用标志位125us
Tss++; //扫描显示用标志位
Tsdisp++;
Disp (); //调用显示扫描程序
if(Ts==6130) //TS=163usX6130=1000ms=1S 由于在外面速度比内里面慢,所以要做在中断
{
Ts=0;
SEC++;
}
/*-------------------------------------------*/
/*if(Ts==2) //测试端口中断
{
Ts=0;
}
switch(Ts)
{case 1: P0=0xFF; break;
case 0: P0=0x00; break;
}*/
/*-------------------------------------------*/
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|