查看: 852|回复: 0
打印 上一主题 下一主题

8254三路计数的程序

[复制链接]
跳转到指定楼层
沙发
发表于 2016-5-30 17:25:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
C语言功底不好,希望大家帮忙优化

另外,把整体的初始化程序分成3个写,出现第二个或第三个计数器高低位读反的情况,这是为什么?



用于小车车速计数使用的

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表