论坛元老
 
- 积分
- 3275
- 金钱
- 3275
- 注册时间
- 2013-9-21
- 在线时间
- 281 小时
|
这是一个数码管绍数板子
要完成的功能是倒数99秒可以8段分别调整计时同时也可以随时记忆
现在遇到的问题是1-8段中调整第六段的值~第七段就会被同步变动一样的值
但1-6和第8段却是正常可以记忆的
24C02也换过很多各了
很奇怪为什么刚好在中间第七段无法记忆且会随着第六段调整时同步被调整
要麻烦原子哥协助修改
以下是主程序代码其他付程序都是用原子哥的
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "24cxx.h"
/*------------------------------------------------------------
端口定义
------------------------------------------------------------*/
#define LATCH1 (1<<8)//
#define LATCH2 (1<<9)//
#define LATCH1_SET(x) GPIOB->ODR=(GPIOB->ODR&~LATCH1)|(x ? LATCH1:0)
#define LATCH2_SET(x) GPIOB->ODR=(GPIOB->ODR&~LATCH2)|(x ? LATCH2:0)
#define DataPort(x) GPIOA->ODR=(GPIOA->ODR&0xffffff00)|(x&0xff);//定义8位数据操作端口
#define KEY0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)//读取启动按键
#define KEY1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)//读取按键1-秒数增加钮
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)//读取按键2-秒数减少钮
#define KEY3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)//读取按键3-9段增加钮
#define KEY4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)//读取按键4-9段减少钮
unsigned char const dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//
unsigned char const dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//
unsigned char Duan[10]={0,0,0,0,0,0,0,0,0,0};//9段倒数阵列中的变数-全部初始化为0防止读取到的值会乱码
unsigned char TempData[8]; //存储显示值的全局变量
void Display(unsigned char FirstBit,unsigned char Num);
void KEY(void);//将所有按钮功能的函数代码都包含在这里面方便主程序调用
void TIM3_Int_Init(u16 arr,u16 psc);//通用定时器3初始化
unsigned char num=0;//number简称num数字的意思这里为全域变数是倒数秒的值-初始化为0秒
unsigned char k=1;//k为9段倒数的阵列中循环用变数-初始化为1
/*------------------------------------------------
主函数
------------------------------------------------*/
int main()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE); //使能GPIOA-B-C时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//选择全部A-PORT脚位
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//IO口速度为最低2M
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//Pin8-Pin9控制74HC573位码-段码Pin10控制蜂鸣器低电位不要发声
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
GPIO_ResetBits(GPIOB,GPIO_Pin_10);//将GPIOB的Pin-10脚 设定为高电位
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;//控制KEY
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB11-12
AFIO->MAPR = (0x00FFFFFF & AFIO->MAPR)|0x04000000; //关闭JTAG
delay_init(); //STM32专用的延时函数
AT24CXX_Init();
NVIC_Configuration();//中断优先权库函数
TIM3_Int_Init(9,719);//定时器3初始化赋于值((9+1)*(719+1)/72=100单位us)
AT24CXX_Read(0,(u8*)Duan,12);
num=Duan[k];
while(1)//主循环
{
KEY();//调用KEY按钮所有库函数
}
}
void Display(unsigned char FirstBit,unsigned char Num)
{
unsigned char i;
for(i=0;i<Num;i++)
{
DataPort(0); //清空数据,防止有交替重影
LATCH1_SET(1); //段锁存
LATCH1_SET(0);
DataPort(dofly_WeiMa[i+FirstBit]); //个位数码
LATCH2_SET(1); //锁存
LATCH2_SET(0);
DataPort(TempData); //段码
LATCH1_SET(1); //锁存
LATCH1_SET(0);
delay_us(20);//调整数码管十位数的明暗度(太高会造成显示不跳动)
}
}
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
TempData[0]=dofly_DuanMa[num/10];//倒数秒数十位数
TempData[1]=dofly_DuanMa[num%10];//倒数秒数个位数-使用定时器来扫描数码管
TempData[2]=dofly_DuanMa[k]; //9段倒数用显示段数
Display(2,3);//2代表0-1-2从第三位数开始显示,3代表共计数三个位数
}
}
void KEY(void)
{
unsigned int key_press_num;//区域变数用于区分长按跟短按变数
unsigned int i=0; //区域变数-倒数累加变数
unsigned int j=0; //区域变数-长时间按钮累加用变数
if(KEY0==0)//如果检测到低电平,说明[启动按键]按下
{
k=1;//当启动按钮按下后先将段数值k=1
num=Duan[k];//将9段倒数阵列移入显示秒num值中-将段数阵列值移入秒值进行倒数运算并同时等同控制显示变数来显示变化
while(1)
{
i++;
if(i==1100000) //循环累加构成延时来启动倒数累减的功能
{
i=0;
if(num>0)//用于显示0~99
{
num--;
}
if(num==0)//当秒值倒数为0时
{
k++;
num=Duan[k];//将段数阵列值移入秒值进行倒数运算并同时等同控制显示变数来显示变化
if(k>8)
{
k=1;
num=Duan[k];//将段数阵列值移入秒值进行倒数运算并同时等同控制显示变数来显示变化必须在倒数值为0时才可给回归指令
break;//此处是为了让while无尽循环达到标准来退回主循环中
}
}
}
}
}
if(!KEY1)
{
delay_us(600); //延时去抖,一般600us为了防止按键弹跳太快
if(!KEY1)
{
delay_us(300); //延时去抖,一般300us
while(!KEY1) //再次确认按键是否按下,没有按下则退
{
key_press_num++;
delay_ms(1);
if(key_press_num==10000) //循环累加构成延时来启动长按钮
{
key_press_num=0;
while(!KEY1) //这里用于识别是否按键还在按下,如果按下执行相关动作,否则退出
{
j++;
if(j==30000) //如果达到长按键标准则进入长按键动作
{
j=0;
if(num<99) //长按钮的累加操作
num++;
TempData[0]=dofly_DuanMa[num/10];
TempData[1]=dofly_DuanMa[num%10];//分解显示信息,如要显示68,则68/10=6 68%10=8
delay_us(200); //用于调节长按循环操作的速度,可以自行调整此值以便达到最佳效果
}
}
}
}
key_press_num=0;
if(num<99) //累加操作
num++;
}
}
if(!KEY2)
{
delay_us(600); //延时去抖,一般600us
if(!KEY2)
{
delay_us(300); //延时去抖,一般300us
while(!KEY2) //再次确认按键是否按下,没有按下则退
{
key_press_num++;
delay_ms(1);
if(key_press_num==8000) //循环累加构成延时来启动长按钮
{
key_press_num=0;
while(!KEY2) //这里用于识别是否按键还在按下,如果按下执行相关动作,否则退出
{
j++;
if(j==30000) //如果达到长按键标准则进入长按键动作
{
j=0;
if(num>0) //长按钮的累减操作
num--;
TempData[0]=dofly_DuanMa[num/10];
TempData[1]=dofly_DuanMa[num%10];//分解显示信息,如要显示68,则68/10=6 68%10=8
delay_us(200); //用于调节长按循环操作的速度,可以自行调整此值以便达到最佳效果
}
}
}
}
key_press_num=0;
if(num>0) //累减操作
num--;
}
}
switch(k) //开关指令用来区分k值1-8分别代表阵列中9个变数-9个变数分别存放9段倒数秒数值
{
case 1:
Duan[1]=num;//将num阵列暂存区的值转9段阵列值-当k=1时代表第一段倒数秒数值
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 2:
Duan[2]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 3:
Duan[3]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 4:
Duan[4]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 5:
Duan[5]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 6:
Duan[6]=num;
AT24CXX_Write(0,(u8*)Duan,12);
case 7:
Duan[7]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
case 8:
Duan[8]=num;
AT24CXX_Write(0,(u8*)Duan,12);
break;
}
//此处按钮定义为9段k变数上调功能
if(!KEY3) //如果检测到低电平,说明按键按下
{
delay_us(500); //延时去抖,一般10-20ms
if(!KEY3) //再次确认按键是否按下,没有按下则退出
{
while(!KEY3);//如果确认按下按键等待按键释放,没有释放则一直等待
{
k++;//加操作
num=Duan[k];//强调在将9段倒数阵列值移回num-因为显示变数为num这样才看得到调整段数在移动的样子
if(k>8) //当段数大于8则循环到1
k=1;
num=Duan[k];//强调在将9段倒数阵列值移回num-因为显示变数为num这样才看得到调整段数在移动的样子
}
}
}
//此处按钮定义为9段k变数下调功能
if(!KEY4) //如果检测到低电平,说明按键按下
{
delay_us(500); //延时去抖,一般10-20ms
if(!KEY4) //再次确认按键是否按下,没有按下则退出
{
while(!KEY4);//如果确认按下按键等待按键释放,没有释放则一直等待
{
k--;//减操作
num=Duan[k];//强调在将9段倒数阵列值移回num-因为显示变数为num这样才看得到调整段数在移动的样子
if(k<1) //当段数少于1则循环到8
k=8;
num=Duan[k];//强调在将9段倒数阵列值移回num-因为显示变数为num这样才看得到调整段数在移动的样子
}
}
}
}
|
|