📄 main.c
字号:
/****************************************Copyright (c)**************************************************
** Modified date: 2007-02
** Version:
** Descriptions: 键盘输入与LED扫描人机对话程序。
**
********************************************************************************************************/
#include "config.h"
#define KEY (1 << 2) // P0.2口(MISO)为按键输入脚
uint8 T0Flag = 0;
uint16 CS[6]={1234,5678,2324,4578,7811,1100}; //可以输入的参数数组
uint8 DATA[8];
uint8 digitable[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示段码表
uint8 selectable[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //显示位码表
uint8 x=0,y=0,k=0; //变量,k对DATA0&DATA1&selectable;x&y对digitable;
uint8 w=0; //显示刷新时间计数器
uint8 SF=0; //闪烁标志位
uint8 TK=0x09; //按键按下记录位寄存器,有效数据位为0~7
uint8 M=0,R=0; //按键选项计数器
uint32 ADC_R[8],ADC_R2;
uint8 i=1;
/*
*********************************************************************************************************
** 函数名称 :ADC_Init()
** 函数功能 :ADC模块初始化
** 入口参数 :无
** 出口参数 :无
*********************************************************************************************************
*/
void ADC_Init(void)
{ PINSEL1 =(1 << 24)| //P0.28连接到AD0.1
(1 << 28); //P0.30连接到AD0.3
AD0CR = 0x0a | // SEL=0x0a,选择通道1、3
((Fpclk / 1000000 - 1) << 8) | // CLKDIV=Fpclk/1000000-1,转换时钟为1MHz
(1 << 16) | // BURST=0,软件控制转换操作
(0 << 17) | // CLKS=0, 使用11clock转换
(1 << 21) | // PDN=1,正常工作模式
(0 << 22) | // TEST1:0=00,正常工作模式
(0 << 24) | // START=1,直接启动ADC转换
(0 << 27); // 直接启动ADC转换时,此位无效
}
//-----------------delayns----------------------
void delays(void)
{ uint16 n,j;
for(n=100;n>0;n--)
for(j=50;j>0;j--);
}
/*-----------------------------------------------*/
/*******************************************************************************************
** 函数名称:IRQ_AD()
** 功能描述:AD中断服务程序
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void __irq IRQ_AD(void)
{
//if(i>2)
// i=1;
uint32 data,chnl;
data=AD0DR;
chnl=(data>>24) & 0x07; //选择通道数
ADC_R[chnl]=(data>>6) & 0x3ff;
//ADC_R2=AD0DR;
//ADC_R2=(ADC_R2 >> 6) & 0x3ff;
ADC_R[chnl] = ADC_R[chnl] * 2480/ 1024; // 将AD结果转换为电压mv值(参考电压经过3/4分压)
// ADC_R2 = ADC_R2 * 2480/ 1024;
// ADC_R2=ADC_R[2];
VICVectAddr = 0;
//AD0CR=AD0CR|(1<<24);
}
/*******************************************************************************************
** 函数名称:Timer0_InitExt()
** 功能描述:TIMER0 初始化
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void Timer0_InitExt(void)
{
T0TC = 0; /* 定时器设置为0 */
T0PR = 0; /* 时钟不分频 */
T0MCR = 0x03; /* 设置T0MR0匹配后复位T0TC,并产生中断标志 */
T0MR0 = Fpclk/400; /* 2.5毫秒定时 */
T0TCR = 0x01; /* 启动定时器 */
}
/*******************************************************************************************
** 函数名称:IRQ_Timer0()
** 功能描述:TIMER0 中断服务程序
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void __irq IRQ_Timer0(void)
{
T0Flag = 1; // T0中断标志置位
T0IR = 0x01; // 清除中断标志
VICVectAddr = 0;
}
/*******************************************************************************************
** 函数名称:IRQ_Init()
** 功能描述:设置定时器0中断IRQ
** 入口参数:无
** 出口参数:无
*******************************************************************************************/
void IRQ_Init(void)
{
VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断
VICVectCntl0 = 0x20 | 4; // 设置定时器0中断通道分配1优先级
VICVectAddr0 = (uint32)IRQ_Timer0; // 设置中断服务程序地址
VICVectCntl1 = 0x20 | 18; // 设置AD中断通道分配最高优先级
VICVectAddr1 = (uint32)IRQ_AD; // 设置AD中断服务程序地址
VICIntEnable = (1 << 4)|(1<<18); // 使能定时器0.AD中断
}
//二进制数转BCD码子程序0
void CONVBIT(uint16 num,uint8 hor)
{
DATA[hor] = num/1000; //计算千位
DATA[hor-1] = num%1000/100; //计算百位
DATA[hor-2] = num%100/10; //计算十位
DATA[hor-3] = num%10/1; //计算个位
return;
}
/********************************************************************************************************
** 函数名称:MSPI_Init()
** 函数功能:初始化SPI接口,设置为主机。
** 入口参数:无
** 出口参数:无
*********************************************************************************************************/
void MSPI_Init(void)
{
//PINSEL0 = (PINSEL0 & 0xFFFF00FF) | 0x00005500; // 设置管脚连接SPI0
PINSEL0 = (PINSEL0 & (~(0xFF << 8))) | (0x55 << 8) ;
//PINSEL1 = (PINSEL0 & 0xFFFF0C03) | 0x00000154; // 设置管脚连接SPI1
PINSEL1 = 0x00000000; // 设置管脚连接GPIO
SPI_SPCCR = 0x52; // 设置SPI时钟分频
SPI_SPCR = (0 << 3) | // CPHA = 0, 数据在SCK 的第一个时钟沿采样
(1 << 4) | // CPOL = 1, SCK 为低有效
(1 << 5) | // MSTR = 1, SPI 处于主模式
(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(0 << 7); // SPIE = 0, SPI 中断被禁止
}
/********************************************************************************************************
** 函数名称:MSPI_SendData()
** 函数功能:向SPI总线发送数据。
** 入口参数:data 待发送的数据
** 出口参数:返回值为读取的数据
********************************************************************************************************/
uint8 MSPI_SendData(uint8 data)
{
SPI_SPDR = data;
while( 0 == (SPI_SPSR & 0x80)); // 等待SPIF置位,即等待数据发送完毕
return(SPI_SPDR);
}
/********************************************************************************************************
** 函数名称:main()
** 函数功能:使用硬件SPI,74HC595驱动控制7段数码管显示。
********************************************************************************************************/
uint8 rcv_data;
int main (void)
{
PINSEL0 = 0x00005500; // 设置SPI管脚连接(P0.5设为GPIO)
MSPI_Init(); // 初始化SPI接口
Timer0_InitExt();
IRQEnable(); // IRQ中断使能
IRQ_Init();
ADC_Init();
while(1)
{
if(T0Flag) //中断定时到
{
while(w==40) //显示数据刷新时间到,执行数据变换。
{
if(M==0) //如果M=0表示运行态,显示运行参数。
{
CONVBIT(ADC_R[1],3);
CONVBIT(ADC_R[3],7);
}
w=0; //清除显示刷新计数器
if(SF) //闪烁标志取反
SF=0;
else
SF=1;
}
if(M==0) //显示扫描送运行参数
{
x=DATA[k];
}
else //否则送修改参数
{
if(k==R) //如果当前显示位与键盘修改位相等,则根据闪烁标志送黑码。
{
if(SF==0)
x=10;
else
x=DATA[k];
}
else
x=DATA[k]; //否则直接送显示数
}
w++; //显示刷新计数器+1。
T0Flag=0; //显示标志位清除。
rcv_data = MSPI_SendData(digitable[x]); // 发送显示数据
rcv_data = MSPI_SendData(selectable[k]); // 发送显示位码
if((IO0PIN&KEY) != 0)
{
if(TK==k) //如果键盘输入位=1且键盘记录位与当前输入位相等,执行键功能。
{
switch(TK) //执行TK键盘号功能0~3。
{
case 0: //0#功能为模式键M+1。
{
if(M==4)
M=1;
else
M++;
switch(M) //取出1~4#参数送显示,以便人机对话修改参数。
{
case 1:
{
CONVBIT(CS[2],4);
CONVBIT(M,0);
}
break;
case 2:
{
CONVBIT(CS[3],4);
CONVBIT(M,0);
}
break;
case 3:
{
CONVBIT(CS[4],4);
CONVBIT(M,0);
}
break;
case 4:
{
CONVBIT(CS[5],4);
CONVBIT(M,0);
}
break;
}
}
break;
case 1: //1#功能为右移键标志位R+1。
{
if(R==3)
R=0;
else
R++;
}
break;
case 2: //2#功能为加键,当前闪烁位+1。
{
if(DATA[R]==9)
DATA[R]=0;
else
DATA[R]++;
}
break;
case 3: //3#功能为回车确认键操作,将修改好的参数送回参数区。
{
while(!M==0)
{
CS[M+1]=DATA[0]*1000+DATA[1]*100+DATA[2]*10+DATA[3];
R=0; //R、M标志归零。
M=0;
}
}
break;
};
TK=0x09; //键记录位清除。
}
}
else if((IO0PIN&KEY) == 0) //如果当前键盘位=0,则再读键盘、延时再读=0则记录键盘位TK=K。
{
delays();
if((IO0PIN&KEY) == 0)
TK=k;
}
if(k==7) //如果键盘扫描计数器K=7,则清除K,否则K+1。
k=0;
else
k++;
}
}
return 0;
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -