/****************************************************
* 安德联CC2530与网关开发板历程zigbee实验1-13
*
* 功能:1、S1按键切换正常模式与睡眠模式
* 2、S2打印当前芯片温度
* 3、串口助手发送"LED_ON@"可开启LED1
* "LED_OFF@"关闭LED1
*
* 日期:2018.7.13
*****************************************************/
#include <ioCC2530.h>
#include <string.h>
#include <stdio.h>
typedef unsigned char u8;
typedef unsigned int u16;
#define ENABLE 1
#define DISABLE 0
#define LED1 P1_0
#define LED2 P1_1
#define S1 (P0_1 == 0 ? 1 : 0)
#define S2 (P2_0 == 0 ? 1 : 0)
u8 SysSleep = 0;
u8 USARTFlag = 0;
u8 USARTCount = 0;
char UsartBuff[50];
float ADC_ConvTem(void);
void Delay_MS(u16 time)
{
u16 i,j;
for(i=0;i<time;i++)
for(j=0;j<1070;j++);
}
/******************** 外设初始化 **************************/
//printf 链接函数
__near_func int putchar(int c)
{
UTX0IF = 0;
U0DBUF = (char)c;
while(UTX0IF == 0);
return(c);
}
void LED_Init(void)
{
P1SEL &= ~0x03; //IO口的类型,0为通用IO,1为复用IO
P1DIR |= 0x03; //IO方向,1为输出,0为输入
}
void KEY_Init(void)
{
//初始化S1 中断模式
P0SEL &= ~0X02; //普通IO模式
P0DIR &= ~0X02; //输入模式
P0INP &= ~0X02; //上下拉模式
P0IFG &= 0; //P0中断状态标志位清零
P0IF = 0; //清中断标志
PICTL |= 0x01; //0上升沿 1下降沿触发
P0IEN |= 0x02; //P0中断使能打开
P0IE = 1; //打开P0中断
EA = 1; //打开总中断
//初始化S2 普通模式
P2SEL &= ~0x01;
P2DIR &= ~0x01;
P2INP &= ~0xa1; //P2输入模式,0为上下拉模式,1为高阻态
}
void TIM3_Init(void)
{
T3CTL |= 0x08; //开启溢出中断
T3CTL |= 0xe0; //TIM1 128分频
T3CTL &= ~0x03; //自动装载模式,从0计数到0xff
T3IE = 1; //打开T1中断
EA = 1; //打开总中断
T3CTL |= 0x10; //开启T3,开始计数
}
void USART_Init(void)
{
//初始化串口0GPIO
PERCFG &= ~0x01; //串口0IO复用到位置1
P0SEL |= 0x0c; //引脚为复用IO
P0DIR |= 0x0c; //引脚方向为输出
P0INP &= ~0x0c; //引脚为上下拉模式
P2INP &= ~0x20; //引脚为上拉
//初始化串口0
U0CSR |= 0x80; //USART模式
U0CSR |= 0x40; //USART接受允许
U0UCR &= ~0x10; //一次传输8位数据
U0UCR &= ~0x08; //奇偶校验关闭
U0UCR &= ~0x04; //1个停止位
U0GCR |= 11; //波特率115200 根据datasheet表格,因为CLK为16M所以12
U0BAUD |= 216; //波特率115200
URX0IE = 1; //使能USART0接收中断
EA = 1; //打开总中断
}
void ADC_Init(void)
{
ADCIE = 0; //关闭ADC中断
ADCIF = 0; //清除标志位
ADCCON1 &= ~0x30; //清零标志位
ADCCON1 |= 0x30; //STSEL 选择启动方式为ST置1控制
ADC_ConvTem(); //ADC前两次转换为异常值
Delay_MS(10);
ADC_ConvTem();
}
void SysPowerMode(u8 mode)
{
if(mode < 4 && mode > 0)
{
SLEEPCMD |= mode;
PCON = 0X01;
}
else PCON = 0;
}
/******************** 功能性函数 **************************/
//串口发送1个byte的数据
void USART_Send(u8 dat)
{
U0DBUF = dat;
URX0IF = 0;
while(UTX0IF==0);
UTX0IF = 0;
}
//串口控制LED
void USART_LED(void)
{
if(USARTFlag)
{
if(!strcmp(UsartBuff,"LED_ON@"))
LED1 = 0;
if(!strcmp(UsartBuff,"LED_OFF@"))
LED1 = 1;
for(u8 i=0;i<USARTCount;i++) //清空缓冲区
{
printf("%c",UsartBuff[i]);
UsartBuff[i] = 0;
}
printf("\r\n");
USARTFlag = DISABLE;
USARTCount = 0;
}
}
//ADC获取芯片内部温度值
float ADC_ConvTem(void)
{
float temp;
P0IE = 0; //P0中断关闭
P0IEN &= ~0x02; //否则ATEST = 1;时会产生P0外部中断
TR0 =1; //连接内部温度传感器,配置此寄存器后,外部中断不能用
ATEST = 1; //连接内部温度传感器
ADCCON2 = 0X3E; //ADCCON2与ADCCON3寄存器,实现效果相同
//ADCCON3 = 0X3E; //选择内部电压为参考电压,12位分辨率
ADCCON1 |= 0x30; //STSEL 选择启动方式为ST置1控制
//转换2次,去除第一次转换时,误差较大的返回值
for(char i =0;i<2;i++)
{
ADCCON1 |= 0x40; //开始转换
while(ADCCON1&0x80 == 0); //等待转换完成
temp = ADCH<<4 | ADCL>>4; //12位分辨率下ADCL右4位无效
temp = (temp - 1367.5)/4.5;
}
TR0 =0; //连接内部温度传感器,配置寄存器后,外部中断不能用
ATEST = 0; //连接内部温度传感器
P0IFG = 0; //清中断标志
P0IE = 1; //P0中断开启
P0IEN |= 0x02; //P0中断使能
return temp;
}
//设置系统时钟位32M
void SetCLK32M(void)
{
CLKCONCMD &= ~0x40;
while(CLKCONSTA&0x40);
CLKCONCMD &= ~0x47;
}
/******************** 主函数 **************************/
int main(void)
{
LED_Init();
TIM3_Init();
USART_Init();
ADC_Init();
SetCLK32M();
KEY_Init();
while(1)
{
//根据S1按键触发的中断标志位切换模式
if(SysSleep)
{
printf("进入睡眠模式\r\n");
Delay_MS(1);
SysPowerMode(3);
Delay_MS(1);
printf("进入正常模式\r\n");
}
//按下S2打印当前芯片温度
if(S2)
{
while(S2);
printf("芯片温度为:%2.2f度\r\n",ADC_ConvTem());
}
//根据串口字符控制LED亮灭
USART_LED();
Delay_MS(100);
}
}
/******************** 中断函数 **************************/
//P0_1 S1按键中断函数
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
SysSleep = !SysSleep;
if(!SysSleep)
{
SysPowerMode(4);
}
P0IFG = 0; //清中断标志
P0IF = 0; //清中断标志
}
//TIM3 定时器中断
#pragma vector = T3_VECTOR
__interrupt void T3_ISR(void)
{
static unsigned int i = 0;
i++;
if(i>244)
{
LED2 = ~LED2; //改变 LED2 状态
i=0;
}
//IRCON寄存器有描述,当进入中断后自动清零标志位
}
//串口0接收中断
#pragma vector = URX0_VECTOR
__interrupt void U0Rx_ISR(void)
{
unsigned char RxBuff;
RxBuff = U0DBUF;
//缓存串口数据,当超过50个字符或者接收到结束符
//缓存数组停止接收数据,只有当MAIN函数处理完数据
//缓存数组才能再次接收数据
if(USARTCount<50 && USARTFlag == DISABLE)
{
UsartBuff[USARTCount] = RxBuff;
USARTCount++;
if(RxBuff == '@')
{
USARTFlag = ENABLE;
}
}
else
{
USARTFlag = ENABLE;
}
//TCON寄存器有描述,当进入中断后自动清零标志位
}
以上程序在开发板上正常运行: