C语言功底不好,希望大家帮忙优化
另外,把整体的初始化程序分成3个写,出现第二个或第三个计数器高低位读反的情况,这是为什么?
8254.rar
(240.75 KB, 下载次数: 6)
2012-4-3 10:12 上传
点击文件名下载附件
用于小车车速计数使用的
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
L8254.H
/*
说明:
主函数中定义
volatile long int num_8254_0,num_8254_1,num_8254_2;
volatile long int speed_count_0,speed_count_1,speed_count_2;
然后包含8254.h和8254.c
首先初始化
void counter_8254_init(void);
就可以直接引用
void counter_8254_read(void);
num_8254_N输出的对应计数器的计数值(从初始化到中断这段时间内)
speed_result(void);
输出的speed_count_N就是编码器转数(如果不需要,则直接使用counter_8254_read)
接线:
12接地 24VCC
引脚1到8 即D7-0接PORTB7-0
23WR接PORTA_PA0
22RD接PORTA_PA1
21CS接PORTA_PA2
20A1接PORTA_PA3
19A0接PORTA_PA4
11GT0接 PORTA_PA5
14GT1接 PORTA_PA6
16GT2接 PORTA_PA7
9CLK0输入0的脉冲
15CLK1输入1的脉冲
18CLK2输入2的脉冲
*/
#ifndef _8254_H
#define _8254_H
#define uchar unsigned char
#define uint unsigned int
#define counter_data_port_dire DDRB //所用的数据口的方向寄存器
#define counter_data_port PORTB //所用的数据口
#define wr PORTA_PA0
#define rd PORTA_PA1
#define CS PORTA_PA2
#define A1 PORTA_PA3
#define A0 PORTA_PA4
#define GT0 PORTA_PA5
#define GT1 PORTA_PA6
#define GT2 PORTA_PA7
#define Count_Time_0 1 //计数的周期,Nms
#define Count_Time_1 1
#define Count_Time_2 1
#define N_Coder_0 500 //编码器线数
#define N_Coder_1 500
#define N_Coder_2 500
void counter_8254_init(void);
void counter_8254_read(void);
void speed_result(void);
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
L8254.C
#include <hidef.h>
#include "derivative.h"
#include "8254.h"
/****************************************
函数void counter_8254_read_N(void)
功能:读8254的N计数器当前计数值
说明:
*******************************************/
void counter_8254_read(void)
{
uint num_L= 0,num_H = 0;
extern long int num_8254_0;
extern long int num_8254_1;
extern long int num_8254_2;
//////////////////////////
counter_data_port_dire = 0xFF;
counter_data_port = 0x00;
A1 = 1;
A0 = 1;
rd = 1;
wr = 0;
CS = 0;
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 0;
A1 = 0;
counter_data_port_dire = 0x00;
num_L = counter_data_port;
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 0;
A1 = 0;
num_H = counter_data_port;
num_L = 0xFF - num_L; //分两次读出,由于82C54是减法计数器,所以要被OxFF减
num_H = 0xFF - num_H;
num_8254_0 = (long int)num_H*256+num_L; //将两个八位整合成一个十六位数据
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 1;
A1 = 0;
counter_data_port_dire = 0x00;
num_L = counter_data_port;
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 1;
A1 = 0;
num_H = counter_data_port;
num_L = 0xFF - num_L; //分两次读出,由于82C54是减法计数器,所以要被OxFF减
num_H = 0xFF - num_H;
num_8254_1 = (long int)num_H*256+num_L; //将两个八位整合成一个十六位数据
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 0;
A1 = 1;
counter_data_port_dire = 0x00;
num_L = counter_data_port;
CS = 1;
wr = 1;
CS = 0;
wr = 1;
rd = 0;
A0 = 0;
A1 = 1;
num_H = counter_data_port;
num_L = 0xFF - num_L; //分两次读出,由于82C54是减法计数器,所以要被OxFF减
num_H = 0xFF - num_H;
num_8254_2 = (long int)num_H*256+num_L; //将两个八位整合成一个十六位数据
}
/****************************************
函数void speed_result(void)
功能:通过计数器的值来计算相应的转速
说明:
*******************************************/
void speed_result(void)
{
extern long int speed_count_0;
extern long int num_8254_0;
extern long int speed_count_1;
extern long int num_8254_1;
extern long int speed_count_2;
extern long int num_8254_2;
counter_8254_read();
speed_count_0 = num_8254_0*(1000/Count_Time_0)/N_Coder_0;
speed_count_1 = num_8254_1*(1000/Count_Time_1)/N_Coder_1;
speed_count_2 = num_8254_2*(1000/Count_Time_2)/N_Coder_2;
}
/****************************************
函数:void counter_8254_init(void)
功能:8254的计数器的初始化
说明:对8254进行控制字写入并设置计数初值
*******************************************/
void counter_8254_init(void)
{
//计数初始化
CS = 0;
GT0 = 1; //#0
GT1 = 1;
GT2 = 1;
CS = 1;
wr = 1;
counter_data_port_dire = 0xFF;
counter_data_port = 0x30; //选择0#。先低8再高8位,方式0,二进制16位计数方式
A1 = 1;
A0 = 1; //写控制字
wr = 0; //写操作
CS = 0;
rd = 1;
CS = 1;
wr = 1;
counter_data_port = 0x70; //选择1#。先低8再高8位,方式0,二进制16位计数方式
A1 = 1;
A0 = 1; //写控制字
wr = 0; //写操作
CS = 0;
rd = 1;
CS = 1;
wr = 1;
counter_data_port = 0xB0; //选择2#。先低8再高8位,方式0,二进制16位计数方式
A1 = 1;
A0 = 1; //写控制字
wr = 0; //写操作
CS = 0;
rd = 1;
CS = 1;
wr = 1;
//////////////////////////
counter_data_port = 0xFF; //低
A0 = 0;
A1 = 0; //#0
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
counter_data_port = 0xFF; //高
A0 = 0;
A1 = 0; //#0
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
//////////////////////////
counter_data_port = 0xFF; //低
A0 = 1;
A1 = 0; //#1
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
counter_data_port = 0xFF; //高
A0 = 1;
A1 = 0; //#1
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
//////////////////////////
counter_data_port = 0xFF; //低
A0 = 0;
A1 = 1; //#2
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
counter_data_port = 0xFF; //高
A0 = 0;
A1 = 1; //#2
rd = 1;
wr = 0; //写
CS = 0;
wr = 1;
CS = 1;
counter_data_port = 0x00;
}
CS = 0;
wr = 1;
rd = 0;
A0 = 0;
A1 = 0;
num_H = counter_data_port;
num_L = 0xFF - num_L; //分两次读出,由于82C54是减法计数器,所以要被OxFF减
num_H = 0xFF - num_H;
num_8254_0 = (long int)num_H*256+num_L; //将两个八位整合成一个十六位数据
你看你上面的A在CS#拉低之后才赋值。所以在这个读周期完成之后才会真正变为0地址。
估计你有得忙了,好多时序都要改。必须要保证CS#有效前WR和RD都是无效的,而且CS无效前WR和RD都变无效。异步读写时序的要求,所有的芯片手册一般都是这样的。
懂了……(⊙o⊙)嗯 还好,这个改起来简单,改一个复制三份就好~~谢谢你了!
一周热门 更多>