⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adc.c

📁 IAR EWARM嵌入式系统编程与实践光盘源码
💻 C
字号:
#include "ADC.h"
#include <stdio.h>
#include <system.h>
#include <rs232.h>
double ADCresmV;

void main(void) {
  SoftwareTimer_t *ptr2Timer = &softTimer[0];
  unsigned int ADCresult;

  initializeInterruptDataStructs();       // 设置软件定时器数据结构
  installTimer(                           // 1秒软件定时器,利用主定时器Timer0匹配方式实现
               ptr2Timer,                 // 当Timer0发生与寄存器MR0匹配时产生中断
               ONE_SEC_TIMER,             // 中断频率为100Hz
               TICKS_PER_1_SEC,
               ONE_SEC_TIMER_INSTALLED
               );


  /* 检测连接器命令文件是否将中断向量安装在0地址,若是则将MEMMAP设为1,使程序从FLASH运行 */
  #pragma segment = "INTVEC"
  if (( void * )0x00000000UL == __segment_begin( "INTVEC" )) {
    MEMMAP = 1;  // 正常FLASH模式
  }
  else {
    MEMMAP = 2 ; // 用户RAM模式-将最低64字节地址空间映射到内部RAM底部,并将异常向量映射到此处
  }

  /* 配置Timer0, 发生与MR0值匹配时产生一次中断 */
  T0IR=0xFF;           // 复位匹配及捕获中断
  T0TCR=0;             // 禁止计数
  T0TC=0;              // 清0定时计数器
  T0PR= 0;             // 无预分频
  T0PC=0;              // 清0预分频定时计数器
  T0MR0=PCLKFREQ/100;  // 计数36864个脉冲,产生100Hz中断,周期 = 10ms
  T0MCR |= (RESET | INT_ON_MATCH);  // 匹配时复位定时计数器与中断
  T0TCR &= ~2;         // 清0 复位标志
  T0TCR = 1;           // 允许计数

  /* 设置VIC,所有中断都分配给IRQ */
  VICIntSelect  =  0;             // 分配所有 VIC 中断给 IRQ
  VICIntEnClear = 0xFFFFFFFF;     // 禁止所有中断
  VICSoftIntClear = 0xFFFFFFFF;   // 清0所有软件中断
  VICProtection = 0;              // 可通过用户或特权模式访问 VIC
  VICVectAddr = 0;                // 清0中断
  VICDefVectAddr = 0;             // 清0默认 ISR 地址

  /* 配置UART1的 RX 和 TX 引脚 */
  PINSEL0 = (1<<ENABLE_UART1_RX) | (1<< ENABLE_UART1_TX);  // PINSEL0 = 0x50000
  // 配置UART1,9600波特率, 8位数据, 1位停止位, 无校验
  U1FCR = 1;                           // 无论是否使用,都允许FIFO
  SetBit(U1LCR,DIVISOR_LATCH_SET_bit); // U1LCR = 0X80 -> 允许访问除数锁存位,以便设置波特率
  U1LCR |= EIGHT_BIT_CHARS;            // 8位数据
  ClrBit(U1LCR,PARITY_ENABLE_bit);     // 无校验
  ClrBit(U1LCR,STOP_BIT_SELECT_bit);   // 1位停止位
  U1DLL = PCLKFREQ / (9600 * 16);
  U1DLM = (PCLKFREQ / (9600 * 16)) >> 8;
  ClrBit(U1LCR,DIVISOR_LATCH_SET_bit); // 禁止访问除数锁存位

  /* 配置ADC0 */
  AD0CR_bit.SEL = 8;                        // 只允许AD0.3
  AD0CR_bit.CLKDIV = PCLKFREQ / 4500000;
  AD0CR_bit.BURST = 1;                      // 连续转换模式
  AD0CR_bit.CLKS = 0;                       // 11时钟/10位精度
  AD0CR_bit.PDN = 1;                        // 上电
  PINSEL1_bit.P0_30 = 1;                    // 配置电位器引脚输出

  /* 配置 VIC 控制寄存器,分配 IRQ 中断 */
  VICProtection = 0;                           // 以用户/保护方式访问 VIC
  VICDefVectAddr = (unsigned int)&NonVectISR;  // 安装默认中断地址

  /* 设置 Timer0 匹配中断 */
  VICIntSelect &= ~(1<<VIC_TIMER0);            // Timer0 IRQ中断
  VICVectAddr0 = (unsigned int)&MM_TIMER0_ISR; // 将中断安装到 VIC 地址 slot
  VICVectCntl0 = 0x20 | VIC_TIMER0;            // IRQ 类型, 允许TIMER0中断
  VICIntEnable |= (1<<VIC_TIMER0);             // 启动Timer0中断

  __enable_interrupt();                         // 允许所有中断

  AD0CR_bit.START = 0x0001;                     // 立即启动第一次转换
  /* 前台循环,用户可加入其他代码,如定时器或按键响应等 */
  while(TRUE) {
    if(softTimer[ONE_SEC_TIMER].us_Event == TIMER_EXPIRED){
      installTimer(                              // 重装1秒定时值
                   ptr2Timer,
                   ONE_SEC_TIMER,
                   TICKS_PER_1_SEC,
                   ONE_SEC_TIMER_INSTALLED
                  );
      /* 获取上次 A/D 转换值,同时启动下一次转换 */
      while(AD0DR_bit.DONE == 0);                // 等待转换结束
      AD0DR_bit.CHN = 0;                         // 通道0数据
      ADCresult = AD0DR_bit.VVDDA ;              // 保存转换值
      ADCresmV = (ADCresult>>2)*3000/256;        // 10位分辨率, 3V最大输入
      printf("potentiometer now reads %4.2f\n\r",ADCresmV);
      AD0CR_bit.START = 0x0001;                  // 启动下一次转换
    }
  }                                              // 前台循环结束
}                                               // 主程序结束

void installTimer (
  SoftwareTimer_t *ptr2Timer,
  unsigned int us_offset,
  unsigned int us_ticks,
  unsigned int us_event
 ) {
  (ptr2Timer+us_offset)->us_Ticks = us_ticks;
  (ptr2Timer+us_offset)->us_Event = us_event;
}

void initializeInterruptDataStructs(void) {
  unsigned int i;
  for(i=0;i<MAX_SOFTWARE_TIMERS;i++) {
    softTimer[i].us_Ticks = 0;
    softTimer[i].us_Event = EVENT_UNDEFINED;
  }
}

/* IRQ中断句柄 */
#pragma vector=0x18
__irq __arm void IRQ_ISR_Handler (void) {
  void (*interrupt_function)();
  unsigned int vector;
  vector = VICVectAddr;     // 获得中断向量
  interrupt_function = (void(*)())vector;
  (*interrupt_function)();  // 通过指针调用向量中断函数
  VICVectAddr = 0;          // 清0 VIC 中断
}

/* TIMER0 中断服务函数 */
void MM_TIMER0_ISR() {
  unsigned int IntType;
  unsigned int i;
  for(i=0; i<MAX_SOFTWARE_TIMERS; i++)
    if(softTimer[i].us_Ticks > 1)            // 如果定时器为减计数
      softTimer[i].us_Ticks--;
    else
      softTimer[i].us_Event = TIMER_EXPIRED; // us_Ticks == 1; 定时时间到
  IntType = (T0IR & 0xFF);                   // 确认中断类型
  T0IR = (IntType & 0xFF);                   // 清0定时器中断
}

/* 非向量中断 */
void NonVectISR(void) {
  while(TRUE);           // 用户程序不会运行到这里
}

void sendByte(char byte) {
    while (!(U1LSR &0x20));  // 当U1THR包含有效数据时,置1 THRE 位
    U1THR = byte;
}

int putchar(int c) {
   while(U1LSR_bit.THRE == 0); // 等待发送就绪
   U1THR = c;                  // 发送字符
   return c;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -