TA的每日心情 | 开心 3 小时前 |
---|
签到天数: 3947 天 连续签到: 18 天 [LV.Master]伴坛终老
|
本帖最后由 toofree 于 2017-1-17 23:39 编辑
【赚周年币】技术帖Week1-Day7——LPC824 Breakout之七、ADC转换,串口同时打印,并同时在 Nokia5110 LCD上显示。
(标题不能太长,没办法,只好在贴中写全名称)
以上一贴最后上传压缩包做主工程模板。参见贴子最末尾的附件。
【赚周年币】技术帖Week1-Day6——LPC824 Breakout之六、30M时钟https://www.cirmall.com/bbs/forum ... 60438&fromuid=17147
在最新的压缩包中“LPC824_Example_Code_Bundle_Keil_r1.0(20170107).rar”,修改了nokia5110 LCD函数名称,并修正了部分Bug。
本贴使用“Example_ADC_Seqa_Seqb”工程模板,做适当修改。完整工程如下图:
主函数如下,红色部分为修改内容。- /*
- ===============================================================================
- Name : Example_ADC_Seqa_Seqb_main.c
- Author : $(author)
- Version :
- Copyright : $(copyright)
- Description : read the readme
- ===============================================================================
- */
- #include "LPC8xx.h"
- //#include <cr_section_macros.h>
- #include <stdio.h>
- #include "lpc8xx_adc.h"
- #include "lpc8xx_swm.h"
- #include "lpc8xx_syscon.h"
- #include "utilities.h"
- #include "nokia5110.h"
- void setup_debug_uart(void);
- const char promptstring[] = "Choose a sequence to convert:\r\na for sequence a\r\nb for sequence b\r\n";
- volatile uint32_t seqa_buffer[12];
- volatile uint32_t seqb_buffer[12];
- volatile enum {false, true} seqa_handshake, seqb_handshake;
- uint32_t current_seqa_ctrl, current_seqb_ctrl;
- // To use software triggering, define this to '1', otherwise define it to '0' to use hardware triggering.
- #define SOFTWARE_TRIGGER 0
- //#define SOFTWARE_TRIGGER 1
- /*****************************************************************************
- *****************************************************************************/
- int main(void) {
- unsigned char temp;
- uint32_t current_clkdiv, val, temp_data, n;
- uint32_t lcd_n=0;
- char lcd_chr[20];
- // Configure the debug uart (see Serial.c)
- setup_debug_uart();
- // Step 1. Power up and reset the ADC, and enable clocks to peripherals (see lpc8xx_syscon.h)
- LPC_SYSCON->PDRUNCFG &= ~(ADC_PD);
- LPC_SYSCON->PRESETCTRL &= (ADC_RST_N);
- LPC_SYSCON->PRESETCTRL |= ~(ADC_RST_N);
- LPC_SYSCON->SYSAHBCLKCTRL |= (ADC | GPIO | SWM);
- // // Make P0.27 output driving '1' connect to P0.11 externally.
- // // Make P0.16 output driving '1', connect to P0.10 externally.
- // LPC_GPIO_PORT->SET0 = 0x08010000; // P0.27, P0.16 to '1'
- // LPC_GPIO_PORT->DIR0 |= 0x08010000; // P0.27, P0.16 to output
-
- // Make P0.15 output driving '1' connect to P0.11 externally.
- // Make P0.16 output driving '1', connect to P0.10 externally.
- LPC_GPIO_PORT->SET0 = 0x00018000; // P0.15, P0.16 to '1'
- LPC_GPIO_PORT->DIR0 |= 0x00018000; // P0.15, P0.16 to output
- // Step 2. Perform a self-calibration
- // Choose a CLKDIV divider value that yields about 500 KHz, we will use the SystemCoreClock variable for the calculation.
- SystemCoreClockUpdate();
- current_clkdiv = (SystemCoreClock / 500000) - 1;
- // Start the self-calibration
- // Calibration mode = true, low power mode = false, CLKDIV = appropriate for 500,000 Hz
- LPC_ADC->CTRL = ( (1<<ADC_CALMODE) | (0<<ADC_LPWRMODE) | (current_clkdiv<<ADC_CLKDIV) );
- // Poll the calibration mode bit until it is cleared
- while (LPC_ADC->CTRL & (1<<ADC_CALMODE));
- // Step 3. Configure the SWM (see utilities_lib and lpc8xx_swm.h)
- // ADC1 - ADC6, ADC7, ADC9 - ADC11 pins to be ADC analog functions
- // We won't use ADC0 or ADC8 because they share pins with the debug uart
- LPC_SWM->PINENABLE0 &= ~(ADC_1|ADC_2|ADC_3|ADC_4|ADC_5|ADC_6|ADC_7|ADC_9|ADC_10|ADC_11); // Fixed pin analog functions enabled
- LPC_SWM->PINENABLE0 |= (ADC_0|ADC_8); // Movable digital functions enabled
- // Assign the ADC pin trigger functions to pins P0.10 (A seq.) and P0.11 (B seq.)
- ConfigSWM(ADC_PINTRIG0, P0_10); // ADC_PINTRIG0 will be for the A sequence
- ConfigSWM(ADC_PINTRIG1, P0_11); // ADC_PINTRIG1 will be for the B sequence
- // Step 4. Configure the ADC for the appropriate analog supply voltage using the TRM register
- // For a sampling rate higher than 1 Msamples/s, VDDA must be higher than 2.7 V (on the Max board it is 3.3 V)
- LPC_ADC->TRM &= ~(1<<ADC_VRANGE); // '0' for high voltage
- // Step 4. Choose a CLKDIV divider value
- // A fully accurate conversion requires 25 ADC clocks.
- // A 30 MHz system clock with CLKDIV = 0 results in 1.2 MSPS.
- // We can use the SystemCoreClock variable to calculate for a desired sample rate in Hz.
- #define desired_sample_rate 1200000
- current_clkdiv = (SystemCoreClock / (25 * desired_sample_rate)) - 1;
- // Calibration mode = false, low power mode = false, CLKDIV = appropriate for desired sample rate.
- LPC_ADC->CTRL = ( (0<<ADC_CALMODE) | (0<<ADC_LPWRMODE) | (current_clkdiv<<ADC_CLKDIV) );
- // Step 5. Assign some ADC channels to each sequence
- // Let sequence A = channels 1, 2, 3, 4, 5, 6
- // Let sequence B = channels 7, 9, 10, 11
- // current_seqa_ctrl = ((1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6))<<ADC_CHANNELS;
- // current_seqb_ctrl = ((1<<7)|(1<<9)|(1<<10)|(1<<11))<<ADC_CHANNELS;
- current_seqa_ctrl = ((1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5))<<ADC_CHANNELS;
- current_seqb_ctrl = ((1<<6)|(1<<7)|(1<<9)|(1<<10)|(1<<11))<<ADC_CHANNELS;
- // Step 6. Select a trigger source for each of the sequences
- // Let sequence A trigger = ADC pin trigger 0. Connected to an external pin through the switch matrix above.
- // Let sequence B trigger = ADC pin trigger 1. Connected to an external pin through the switch matrix above.
- #if SOFTWARE_TRIGGER
- current_seqa_ctrl |= LOGIC_HIGH<<ADC_TRIGGER; // Use for software-only triggering
- current_seqb_ctrl |= LOGIC_HIGH<<ADC_TRIGGER; // Use for software-only triggering
- #else
- current_seqa_ctrl |= ADC_PINTRIG_0<<ADC_TRIGGER; // Use for hardware triggering
- current_seqb_ctrl |= ADC_PINTRIG_1<<ADC_TRIGGER; // Use for hardware triggering
- #endif
- // Step 7. Select positive (1) or negative (0) edge for the hardware trigger
- // Let sequence A be negative edge triggered
- // Let sequence B be negative edge triggered
- current_seqa_ctrl |= 0<<ADC_TRIGPOL;
- current_seqb_ctrl |= 0<<ADC_TRIGPOL;
- // Step 8. Choose (1) to bypass, or (0) not to bypass the hardware trigger synchronization
- // Since our trigger sources are on-chip, system clock based, we may bypass.
- current_seqa_ctrl |= 1<<ADC_SYNCBYPASS;
- current_seqb_ctrl |= 1<<ADC_SYNCBYPASS;
- // Step 9. Choose burst mode (1) or no burst mode (0) for each of the sequences
- // Let sequences A and B use no burst mode
- current_seqa_ctrl |= 0<<ADC_BURST;
- current_seqb_ctrl |= 0<<ADC_BURST;
- // Step 10. Choose single step (1), or not (0), for each sequence.
- // Let sequences A and B use no single step
- current_seqa_ctrl |= 0<<ADC_SINGLESTEP;
- current_seqb_ctrl |= 0<<ADC_SINGLESTEP;
- // Step 11. Choose A/B sequence priority
- // Use default
- current_seqa_ctrl |= 0<<ADC_LOWPRIO;
- // Step 12. Choose end-of-sequence mode (1), or end-of-conversion mode (0), for each sequence
- // Let sequences A and B use end-of-sequence mode
- current_seqa_ctrl |= 1<<ADC_MODE;
- current_seqb_ctrl |= 1<<ADC_MODE;
- // Step 13. Set the low and high thresholds for both sets of threshold compare registers
- // Note: This step is included for completeness, threshold crossings are not currently used in this example.
- // Let both low thresholds be (1/3)*0xfff
- // Let both high thresholds be (2/3)*0xfff
- #define low_thresh (0xFFF / 3)
- #define high_thresh ((2 * 0xFFF) / 3)
- LPC_ADC->THR0_LOW = low_thresh;
- LPC_ADC->THR1_LOW = low_thresh;
- LPC_ADC->THR0_HIGH = high_thresh;
- LPC_ADC->THR1_HIGH = high_thresh;
- // Step 14. For each channel, choose which pair of threshold registers (0 or 1) conversion results should be compared against.
- // Note: This step is included for completeness, threshold crossings are not currently used in this example.
- // For sequence A (channels 1 - 6), compare against threshold register set 0
- // For sequence B (channels 7, 9, 10, 11), compare against threshold register set 1
- LPC_ADC->CHAN_THRSEL = (0<<1)|(0<<2)|(0<<3)|(0<<4)|(0<<5)|(0<<6)|(1<<7)|(1<<9)|(1<<10)|(1<<11);
- // Step 15. Choose which interrupt conditions will contribute to the ADC interrupt/DMA triggers
- // Only the sequence A and sequence B interrupts are enabled for this example
- // SEQA_INTEN = true
- // SEQB_INTEN = true
- // OVR_INTEN = false
- // ADCMPINTEN0 - ADCMPEN11 = false
- LPC_ADC->INTEN = (1<<SEQA_INTEN) |
- (1<<SEQB_INTEN) |
- (0<<OVR_INTEN) |
- (0<<ADCMPINTEN0) |
- (0<<ADCMPINTEN1) |
- (0<<ADCMPINTEN2) |
- (0<<ADCMPINTEN3) |
- (0<<ADCMPINTEN4) |
- (0<<ADCMPINTEN5) |
- (0<<ADCMPINTEN6) |
- (0<<ADCMPINTEN7) |
- (0<<ADCMPINTEN8) |
- (0<<ADCMPINTEN9) |
- (0<<ADCMPINTEN10)|
- (0<<ADCMPINTEN11);
- // Write the sequence control word with enable bit set for both sequences
- current_seqa_ctrl |= 1U<<ADC_SEQ_ENA;
- LPC_ADC->SEQA_CTRL = current_seqa_ctrl;
- current_seqb_ctrl |= 1U<<ADC_SEQ_ENA;
- LPC_ADC->SEQB_CTRL = current_seqb_ctrl;
- // Enable ADC interrupts in the NVIC
- NVIC_EnableIRQ(ADC_SEQA_IRQn);
- NVIC_EnableIRQ(ADC_SEQB_IRQn);
-
- Home_Init();
- NOKIA5110_init();
- NOKIA5110_clear_screen();
-
- NOKIA5110_display_1608_text (0, 0, "LPC824");
- NOKIA5110_display_8x6_text (0, 2, "ADC Test !");
- printf("This is a ADC test programme !\r\n");
- printf("low_thresh: 0x%03X\r\n",low_thresh);
- printf("high_thresh: 0x%03X\r\n",high_thresh);
- while(1) {
- // Prompt user to select a sequence to convert (see utilities_lib)
- temp = GetConsoleCharacter((const char *)&promptstring);
- // Accept 'a' only, anything else is sequence B
- if (temp == 'a') {
- seqa_handshake = false;
- #if SOFTWARE_TRIGGER
- // Launch sequence A with software
- current_seqa_ctrl |= 1<<ADC_START;
- LPC_ADC->SEQA_CTRL = current_seqa_ctrl;
- #else
- // Launch sequence A with hardware
- LPC_GPIO_PORT->CLR0 = 0x00010000; // Clear P0.16 to '0', creates a falling edge on ADC_PINTRIG0
- #endif
- // Wait for return from ISR
- while (!seqa_handshake);
-
- printf("\r\n");
- NOKIA5110_clear_screen();
- lcd_n = 0;
- // Get the data from SRAM and print it to the terminal
- for (n = 0; n < 12; n++) {
- val = current_seqa_ctrl;
- val = (val>>n) & 0x1; // Shift the current channel of interest into bit 0, see if it's set
- if (val) { // If set, get this channel's data from the SRAM array
- temp_data = (seqa_buffer[n]>>4) & 0x00000FFF;
- printf("ADC channel %d data was %d\r\n", n, temp_data);
-
- NOKIA5110_display_8x6_text (0, lcd_n, "ADC");
- sprintf(lcd_chr,"%2d",n);
- NOKIA5110_display_8x6_text (18, lcd_n, lcd_chr);
- NOKIA5110_display_8x6_text (30, lcd_n, ": 0x");
- sprintf(lcd_chr,"%4d",temp_data);
- NOKIA5110_display_8x6_text (54, lcd_n, lcd_chr);
- lcd_n++;
- }
- }
- }
- else if (temp == 'b'){
- seqb_handshake = false;
- #if SOFTWARE_TRIGGER
- // Launch sequence B with software
- current_seqb_ctrl |= 1<<ADC_START;
- LPC_ADC->SEQB_CTRL = current_seqb_ctrl;
- #else
- // Launch sequence B with hardware
- //LPC_GPIO_PORT->CLR0 = 0x08000000; // Clear P0.27 to '0', creates a falling edge on ADC_PINTRIG1
- LPC_GPIO_PORT->CLR0 = 0x00008000; // Clear P0.15 to '0', creates a falling edge on ADC_PINTRIG1
- #endif
- // Wait for return from ISR
- while (!seqb_handshake);
-
- printf("\r\n");
- NOKIA5110_clear_screen();
- lcd_n = 0;
- // Get the data from SRAM and print it to the terminal
- for (n = 0; n < 12; n++) {
- val = current_seqb_ctrl;
- val = (val>>n) & 0x1; // Shift the current channel of interest into bit 0, see if it's set
- if (val) { // If set, get this channel's data from the SRAM array
- temp_data = (seqb_buffer[n]>>4) & 0x00000FFF;
- printf("ADC channel %d data was %d\r\n", n, temp_data);
-
- NOKIA5110_display_8x6_text (0, lcd_n, "ADC");
- sprintf(lcd_chr,"%2d",n);
- NOKIA5110_display_8x6_text (18, lcd_n, lcd_chr);
- NOKIA5110_display_8x6_text (30, lcd_n, ": 0x");
- sprintf(lcd_chr,"%4d",temp_data);
- NOKIA5110_display_8x6_text (54, lcd_n, lcd_chr);
- lcd_n++;
- }
- }
- }
- else
- {
- printf("\r\nInput error, please input again! \r\n");;
- }
- // Put the external pins back to '1'
- //LPC_GPIO_PORT->SET0 = 0x08010000; // Set P0.27, P0.16 to '1'
- LPC_GPIO_PORT->SET0 = 0x00018000; // Set P0.15, P0.16 to '1'
-
- } // end of while 1
- } // end of main
复制代码 在代码中标注红色时出现问题,全乱了,下面截图说明。选中的蓝色字部分为添加或修改的程序。
添加nokia5110 LCD函数库支持
之前默认是\n\r,结果打印不换行,修改成“\r\n”
lcd显示行计数和字符串缓存
原本是P0.27,改为P0.15。因为nokia5110 LCD显示用了5个IO,从P0.24到P0.28。
把ADC6通道从seqa换到了seqb,这样匀一下方便显示
在while之前,对LCD初始化并显示,串口也打印部分信息
在seqa中,每次进入seqa时,清屏LCD
对seqa中通道及电压在LCD上显示。245行有改动,NOKIA5110_display_8x6_text (30, lcd_n, ": ");
改成判断字符'b',这样程序有效的字符只有'a'和'b'
在seqb中,每次进入seqb时,清屏LCD
同上,281行有改动,NOKIA5110_display_8x6_text (30, lcd_n, ": ");
输入字符除‘a’、'b'外,都显示输入错误提示。
实验连线,P0.15、P0.16分别与P0.11、P0.10连接,P0.24到P0.28接Nokia5110 LCD。模拟电压是通过LPC824 Lite板卡给提供的,存在干扰,但能看出AD效果来。P0.06接LPC824 Lite的电位器管脚,地线不用连(因为在LPC824 Breakout板上只有一根地线共LCD用了),通过USB共地。
原理图接线
实物连接,全家福。
下载程序,复位后开始跑程序,串口终端显示。
LCD显示
输入'a'+空格,后开始seqa AD转换,结果显示在串口终端和LCD上
LCD显示
输入'b'+空格,后开始seqb AD转换,结果显示在串口终端和LCD上
LCD显示结果
LPC824 Breakout AD转换,结果成功显示在串口终端打印,并成功在LCD上显示。完美收工^_^。
依照惯例, 修改后工程文件打包附上。
LPC824_Example_Code_Bundle_Keil_r1.0(201701072334).rar
(2.34 MB, 下载次数: 46)
|
评分
-
查看全部评分
|