BÀI 08: LẬP TRÌNH ADC SMT32

posted in: Vi điều khiển | 0

1. Giới thiệu về ADC

  • ADC – Analog to digital convert là bộ chuyển đổi tín hiệu tương tự sang số. Tín hiệu tương tự là điện áp Vin được so sánh với điện áp tham thiếu Vref, sau đó được chuyển đổi thành số lưu vào thanh ghi DATA của bộ chuyển đổi đó. العاب بوكر ADC được ứng dụng rất nhiều như đo nhiệt độ, đọc giá trị điện áp, cường độ dòng điện, đọc phím nhấn, đọc giá trị biến trở, bảo vệ động cơ….Khi tìm hiểu về ADC chúng ta cần tìm hiểu bộ ADC đó là bao nhiêu bit hay độ phân giải, các phương pháp chuyển đổi. لعبة جاك بوت ADC có số bit càng cao tức là độ phân giải của bộ ADC càng lớn.
  • STM32F103C8 có 2 kênh ADC đó là ADC1 và ADC2, độ phân giải mỗi kênh là 12 bit tức là giá trị đọc về nằm trong khoảng 0 ->2^12 -1 = 4095, có tối đa là 9 channel với nhiều mode hoạt động như: single, continuous, scan hoặc discontinuous.
  • Diagram của single ADC trong STM32F103:




  • Với chế độ Single bộ ADC chỉ chuyển đổi 1 lần rồi dừng, một sự kiện ngắt được sinh ra nếu bit EOCIR được set lên 1.
  • Với chế độ Continuous bộ ADC sẽ chuyển đổi liên tục, một sự kiện ngắt được sinh ra nếu bit EOCIR được set lên 1.

Cơ chế để tạo ADC như sau:

  • Enable bộ clock cho ADC, ghi hệ số chia cho ADC prescaler
  • Chọn các kênh cần chuyển đổi
  • Chọn chế độ chuyển đổi Sinlge, Continuous, Scan, Discontinuous
  • Chọn thời gian lấy mẫu (Sampling Time)
  • Chọn Ngắt hoặc DMA
  • Start bộ chuyển đổi
  • Kiểm tra cờ EOC hoặc trong ngắt đọc dữ liệu từ thanh ghi DR về

2. Lập trình ADC với thư viện chuẩn của ST

Yêu cầu: Cấu hình sử dụng bộ ADC1 kênh 0 trên chân PA0 đọc giá trị biến trở hiển thị lên máy tính thông qua UART1. Để chương trình trong hàm main.c trở nên gọn hơn, trong bài này mình sẽ tạo các file thư viện.

void Adc_Init(ADC_TypeDef* ADCx, uint8_t channel) {

ADC_InitTypeDef ADC_InitDef;
DMA_InitTypeDef DMA_InitStructure;
	
if (channel == ADC_Channel_0) {
ADC_INT_Channel_0_Init(ADCx);
} else if (channel == ADC_Channel_1) {
ADC_INT_Channel_1_Init(ADCx);
} else if (channel == ADC_Channel_2) {
ADC_INT_Channel_2_Init(ADCx);
} else if (channel == ADC_Channel_3) {
ADC_INT_Channel_3_Init(ADCx);
} else if (channel == ADC_Channel_4) {
ADC_INT_Channel_4_Init(ADCx);
} else if (channel == ADC_Channel_5) {
ADC_INT_Channel_5_Init(ADCx);
} else if (channel == ADC_Channel_6) {
ADC_INT_Channel_6_Init(ADCx);
} else if (channel == ADC_Channel_7) {
ADC_INT_Channel_7_Init(ADCx);
} else if (channel == ADC_Channel_8) {
ADC_INT_Channel_8_Init(ADCx);
} else if (channel == ADC_Channel_9) {
ADC_INT_Channel_9_Init(ADCx);
} 
if (ADCx == ADC1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);		
} else if (ADCx == ADC2) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

  }       
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)0x4001244C);
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  /* Enable DMA1 channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);
  ADC_InitDef.ADC_Mode = ADC_Mode_Independent;
  ADC_InitDef.ADC_ScanConvMode = ENABLE;
  ADC_InitDef.ADC_ContinuousConvMode = ENABLE;
  ADC_InitDef.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitDef.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitDef.ADC_NbrOfChannel = 1;	
/* Initialize ADC */
  ADC_Init(ADCx, &ADC_InitDef);
 /* Enable ADCx DMA */
  ADC_DMACmd(ADCx, ENABLE);

 /* Enable ADC */
  ADC_Cmd(ADCx, ENABLE);
/* Calib ADC */
 ADC_ResetCalibration(ADCx);	 
 while(ADC_GetResetCalibrationStatus(ADCx));	
	
  ADC_StartCalibration(ADCx);
  while(ADC_GetCalibrationStatus(ADCx));	
 /* Start ADC1 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}
  • Chương trình trong hàm main.c

int main(void)
 {	
	 u8 c=0;
	 u16 adcx=0;
	 float  temp=0;
	 char buffer[100];
         delay_init();
         /* Cau hinh UART */
	 USARTx_Init(USART1, Pins_PA9PA10, 115200);
         /* Cau hinh adc */   
	 Adc_Init(ADC1,ADC_Channel_0);
  while(1)
	{
        /* Doc gia tri tren chan PA0 */		
	temp=(float)ADC_ConvertedValue*(3.3/4096);
        /* Truyen du lieu len PC qua uart1 */	
	printf("%f\n",temp);
	delay_ms(250);
	
	}
 }

Kết quả đo được:

Link code mẫu

Trả lời

Email của bạn sẽ không được hiển thị công khai.