今天我们来结合代码说一下C8051的基础配置,包括:GPIO、晶振、定时器、和串口。其他外设留待下次。
首先是GPIO配置:
先说一下与GPIO相关的几个寄存器:PxMDIN,PxMDOUT,PxSKIP,XBR0,XBR1,XBR2。
PxMDIN,输入模式寄存器。0代表模拟输入,1代表数字输入。比如配置P0口,0:3口是数字,4:7口是模拟。我们就可以配置P0MDIN=0x0F;
PxMDOUT,输出模式寄存器。在输入为数字模式的基础下,0代表开漏输出,1代表推挽输出。
PxSKIP:交叉开关跳过控制寄存器。这个寄存器要着重说一下。这个可能是C8051特有的了。
我们可以看到优先级最高的外设就是串口0了。如果我们启用了串口0,他的引脚就是P0.4和P0.5
然后我们以外部中断0(CEX0)为例,如果我们启用了外部中断零,他的最高优先级备选引脚就是P0.0。这时假设我们已经配置过了spi,并且spi的SCK配置为了P0.0。那么这个时候外部中断0的引脚就成了P0.1。高优先引脚被占用的情况下自动选择下一个优先级的引脚。这个时候,假设我们配置P0SKIP=0000 0010。P0.1配置为了跳过,这时候外部中断0的引脚就是P0.2。
void PORT_Init(void)
{
U8 SFRPAGE_save = SFRPAGE; //记录当前SFR页面
SFRPAGE = CONFIG_PAGE; //转到需要设置的SFR
/*************************晶振引脚初始化***********************************/
P0MDIN &= ~0x0C; // P0.2, P0.3 are analog
P0SKIP |= 0x0C; // P0.2, P0.3 skipped in the Crossbar
XBR1 = 0x02; // Route /SYSCLK to crossbar
XBR2 = 0x40; // Enable crossbar and weak pull-ups
/*************************************************************************/
P1MDOUT = 0xFB;
P1SKIP = 0xFF;
P1MDIN = 0xFF;
XBR0 = 0x01; //串口0
SFRPAGE = SFRPAGE_save;//恢复寄存器页面
}
然后是晶振初始化配置:
C8051单片机集成了内部晶振,最高可以达到25MHZ。我们可以根据自己需要配置时钟。
先说一下与晶振相关的几个寄存器:
OSCICN:内部时钟相关的配置
RSTSRC :系统时钟安全性检查及标志位(包含看门狗,时钟缺失等标志位)
OSCXCN:外部时钟控制
CLKSEL:时钟源的选择(默认为内部时钟,不倍频)
接下来上代码:
例一内部时钟初始化:
void OSCILLATOR_Init(void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
OSCICN = 0x87;
RSTSRC = 0x04; //开启丢失时钟检测
SFRPAGE = SFRPAGE_save;
}
例二外部时钟初始化:
void OSCILLATOR_Init(void)
{
U16 i; // Delay counter
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
RSTSRC = 0x06; // Enable missing clock detector and
// VDD Monitor reset
SFRPAGE = CONFIG_PAGE;
OSCXCN = (0x60 | 5); // Start external oscillator with
// the appropriate XFCN setting
// based on crystal frequency
for (i = 0; i < 256; i++); // Wait for crystal osc. to start
while (!(OSCXCN & 0x80)); // Wait for crystal osc. to settle
CLKSEL = 0x01; // Select external oscillator as system
// clock source
OSCICN = 0x00; // Disable the internal oscillator.
SFRPAGE = SFRPAGE_save;
}
定时器初始化配置
C8051的定时器相对比较简单,相较于51单片机没有什么变化。
定时器相关的寄存器:
CKCON:可以配置定时器的时钟源和分频系数等
TMOD,TCON:定时器0和1相关的配置
TL0,TH0:定时器0的装载值
TL1,TH1:定时器1的装载值
TMR2CN:定时器2的相关配置
TMR2L,TMR2H:定时器2的预装载值
TMR2RLL,TMR2RLH:定时器2的重装载值(定时器2是自动重装载的寄存器)
定时器3和定时器2相似,这里就不详细的说了 。
上代码:
定时器0初始化:
void Uart0_Init(void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
SBRLH0=0xff;
SBRLL0=0xD0;
SBCON0 |= 0x03; // Set prescaler to 1
SBCON0 |= 0x40; // Enable baud rate generator
//SMOD0 = 0x0c; //0000 1100
ES0 = 1; // Enable UART0 interrupts
SFRPAGE = ACTIVE_PAGE;
SCON0 |= 0x10;
SFRPAGE = SFRPAGE_save;
}
定时器0中断函数:
INTERRUPT_PROTO (TIMER0_ISR, INTERRUPT_TIMER0);
INTERRUPT (TIMER0_ISR, INTERRUPT_TIMER0)
{
TH0 = 0xF4;
TL0 = 0x00;
}
串口配置:
串口相关寄存器:
SCON0 : 各种标志位(比如:接收中断标志,发送标志位等)
SMOD0:串口0配置(包括:数据长度,停止位长度,校验类型选择)
SBUF0:串口收发缓存区
SBCON0:波特率发生器使能和分频控制
SBRLL0,SBRLH0:波特率控制
波特率计算:Baud Rate=[SYSCLK/(65536-(SBRLH0:SBRLL0))] /2 /Prescaler
OK,上代码:
void Uart0_Init(void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
SBRLH0=0xff;
SBRLL0=0xD0;
SBCON0 |= 0x03; // Set prescaler to 1
SBCON0 |= 0x40; // Enable baud rate generator
//SMOD0 = 0x0c; //0000 1100
ES0 = 1; // Enable UART0 interrupts
SFRPAGE = ACTIVE_PAGE;
SCON0 |= 0x10;
SFRPAGE = SFRPAGE_save;
}
串口接收:
INTERRUPT_PROTO (UART0_ISR, INTERRUPT_UART0);
INTERRUPT(UART0_ISR, INTERRUPT_UART0)
{
if (RI0)
{
RI0 = 0;
receByte = SBUF0;
}
}
串口发送:
void Putchar(U8 a)
{
SBUF0 =a;
while (!TI0);
TI0 = 0;
}
断断续续的写了好多天才写完,关于C8051的其他外设后期可能还会有补充。喜欢的朋友可以关注下。